Herstellen einer Verbindung mit einem USB-Gerät (UWP-App)
Unter Windows können Sie eine UWP-App schreiben, die mit einem USB-Gerät interagiert.
Dieser Artikel beschreibt Folgendes:
- Verwenden des DeviceWatcher-Objekts zum Erkennen von Geräten
- Öffnen des Geräts für die Kommunikation
- So schließen Sie das Gerät, wenn Sie es nicht mehr verwenden
Wichtige APIs
Wenn Sie eine UWP-App schreiben, die mit einem USB-Gerät interagiert, kann die App Steuerungsbefehle senden, Geräteinformationen abrufen sowie Daten an bzw. von Massenendpunkten lesen und schreiben. Bevor Sie all dies tun können, müssen Sie das Gerät finden und eine Verbindung herstellen.
Vorbereitung
- Dies ist das erste Thema in einer Reihe. Bevor Sie mit diesem Tutorial beginnen, müssen Sie ein einfaches Visual Studio-Projekt erstellt haben, das Sie in diesem Tutorial erweitern können. Weitere Informationen finden Sie unter Erste Schritte mit UWP-Apps .
- Codebeispiele basieren auf dem CustomUsbDeviceAccess-Beispiel. Sie können das vollständige Beispiel von dieser Codekatalogseite herunterladen.
- Das im Tutorial verwendete USB-Gerät ist das SuperMUTT-Gerät.
- Um den Windows.Devices.Usb-Namespace zum Schreiben einer Windows-App zu verwenden, die mit einem USB-Gerät interagiert, muss der Winusb.sys Treiber als Funktionstreiber geladen sein. Winusb.sys wird von Microsoft bereitgestellt und ist in Windows im Ordner \Windows\System32\drivers enthalten.
Flussdiagramm: Suchen des Geräts
Um eine Verbindung mit einem USB-Gerät herzustellen, müssen Sie zunächst das Gerät basierend auf verschiedenen Ermittlungsmustern suchen und dann eine Verbindung mit dem Gerät herstellen:
- Verbinden Sie ein beliebiges USB-Gerät mit einer bestimmten Geräteschnittstellen-GUID.
- Stellen Sie eine Verbindung mit einem USB-Gerät mit einer bestimmten Anbieter- und Produkt-ID her, das über eine bestimmte Geräteschnittstellen-GUID verfügt.
- Stellen Sie eine Verbindung mit einem USB-Gerät mit einer bestimmten Anbieter- und Produkt-ID her, ohne die GUID der Geräteschnittstelle zu kennen.
- Stellen Sie eine Verbindung mit einem USB-Gerät her, das über eine bekannte Geräteklasse verfügt.
Wichtige Begriffe
Was ist eine GUID für die Geräteschnittstelle?
Ein Kernelmodelltreiber registriert während seiner Initialisierung eine GUID, die als GERÄTEschnittstellen-GUID bezeichnet wird, und macht sie verfügbar. In der Regel verwendet die App die verfügbar gemachte GUID, um den zugeordneten Treiber und das zugehörige Gerät zu finden und dann ein Handle für das Gerät zu öffnen. Das abgerufene Handle wird für nachfolgende Lese- und Schreibvorgänge verwendet.
Im Fall von Winusb.sys kann sie jedoch auf eine von zwei Arten bereitgestellt werden, anstatt dass der Treiber die Geräteschnittstellen-GUID verfügbar macht:
- In den MS OS-Deskriptoren des Geräts. Der Gerätehersteller legt DeviceInterfaceGUID als benutzerdefinierte Eigenschaft im Deskriptor für erweiterte Eigenschaften auf dem Gerät fest. Weitere Informationen finden Sie im Dokument "Erweiterte Eigenschaftendeskriptoren" in Microsoft-Betriebssystemdeskriptoren.
- Wenn Sie Winusb.sys manuell über ein benutzerdefiniertes INF installiert haben, hat das INF eine GUID im INF registriert. Weitere Informationen finden Sie unter WinUSB (Winusb.sys) Installation.
Wenn eine Geräteschnittstellen-GUID für das Gerät gefunden wird, kann Ihre UWP-App alle Geräte finden, die dieser Geräteschnittstellen-GUID entsprechen.
Wie wird die USB-Geräteidentifikation in Windows angezeigt?
Jedes USB-Gerät muss über zwei Informationen verfügen: Anbieter-ID und Produkt-ID.
USB-IF weist diese Bezeichner zu, und der Gerätehersteller muss sie im Gerät verfügbar machen. Wie können Sie also diese Informationen erhalten?
Auch wenn auf dem Gerät kein Gerätetreiber geladen ist, d. h. Windows diesen als "Unbekanntes Gerät" erkennt, können Sie die Bezeichner im Geräte-Manager im Wert der Hardware-ID-Eigenschaft anzeigen. Dieser Wert ist eine Kombination dieser beiden Bezeichner. Beispielsweise lautet die Hardware-ID für das SuperMUTT-Gerät "USB\VID_045E&PID_F001". Die Anbieter-ID ist "0x045E" und die Produkt-ID ist "0xF001".
Wenn ein INF für das Gerät vorhanden ist, rufen Sie diese Zeichenfolge aus dem Abschnitt Modelle ab.
Sie können verschiedene Registrierungseinstellungen überprüfen. Die einfachste Möglichkeit besteht darin, die
<HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Enum\USB\Hardware-ID>
Weitere Informationen finden Sie unter USB-Geräteregistrierungseinträge.
Die Hardware-ID wird vom App-Manifest verwendet, um das Gerät zu identifizieren.
<Device Id="vidpid:045e f001">
Ihre UWP-App kann alle Geräte finden, die mit einem bestimmten Anbieter und produkt-IDs übereinstimmen. Sie können die Suchergebnisse einschränken, indem Sie die GUID der Geräteschnittstelle angeben.
Was sind USB-Geräteklassen?
Die meisten USB-Geräte entsprechen den Geräteklassenspezifikationen, die von USB-IF genehmigt wurden. Durch die Verwendung dieser Spezifikationen können Geräte ähnlicher Art ihre Funktionalität standardmäßig zeigen. Der größte Vorteil dieses Ansatzes besteht darin, dass das Gerät einen von Microsoft bereitgestellten In-Box-Klassentreiber oder den generischen Winusb.sys-Treiber verwenden kann.
Einige Geräte folgen möglicherweise nicht der USB-IF-Spezifikation. Stattdessen machen sie vom Anbieter definierte Funktionen verfügbar. Für solche Geräte muss entweder der Hersteller den Gerätetreiber angeben, oder Winusb.sys verwendet werden kann.
Unabhängig davon, ob ein Gerät vom Hersteller definiert ist oder einer Geräteklasse entspricht, muss es diese Geräteklassenbezogene Informationen beschreiben:
- Klassencode: Gibt die Geräteklasse an, zu der das Gerät gehört.
- Unterklassencode: Innerhalb der Geräteklasse gibt die Unterklasse des Geräts an.
- Protokollcode: Das Vom Gerät verwendete Protokoll.
Das SuperMUTT-Gerät ist beispielsweise ein vom Hersteller definiertes Gerät, und diese Informationen, die durch den Klassencode angegeben werden, sind FF. Wenn Ihr Gerät Klassencode als FEh, Unterklassencode als 02h und Protokollcode 00h anzeigt, können Sie daraus schließen, dass es sich bei dem Gerät um ein klassenkonformes IrDA-Bridgegerät handelt. Ihre UWP-App kann mit Geräten kommunizieren, die zu diesen Geräteklassen gehören:
- ActiveSync
- CdcControl
- DeviceFirmwareUpdate
- IrDA
- Messung
- PalmSync
- PersonalHealthcare
- Physisch
- VendorSpecific
Ihre UWP-App kann alle Geräte finden, die mit einem bestimmten Satz von Klassen-, Unterklassen- und Protokollcodes übereinstimmen.
Abrufen der AQS-Zeichenfolge (Advanced Query Syntax) für das Gerät
Generieren Sie eine erweiterte Abfragezeichenfolge (Advanced Query String, AQS), die Identifikationsinformationen zu dem Gerät enthält, das Sie erkennen möchten. Sie können die Zeichenfolge generieren, indem Sie entweder die Anbieter-/Produkt-IDs, die Geräteschnittstellen-GUID oder die Geräteklasse angeben.
Wenn Sie die Anbieter-ID/Produkt-ID oder die Geräteschnittstellen-GUID angeben möchten, rufen Sie eine beliebige Überladung von GetDeviceSelector auf.
Im Beispiel des SuperMUTT-Geräts ruft GetDeviceSelector eine AQS-Zeichenfolge ab, die der folgenden Zeichenfolge ähnelt:
"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"
Hinweis Beachten Sie, dass die in der Zeichenfolge angezeigte Geräteschnittstellen-GUID nicht die von Ihnen angegebene ist. Diese GUID ist die tatsächliche GUID der Geräteschnittstelle, die von Winusb.sys für UWP-Apps registriert wurde.
Wenn Sie die Geräteklasse des Geräts oder deren Klassen-, Unterklassen- und Protokollcodes kennen, rufen Sie GetDeviceClassSelector auf, um die AQS-Zeichenfolge zu generieren.
Erstellen Sie ein UsbDeviceClass-Objekt , indem Sie die Eigenschaftenwerte ClassCode, SubclassCode und ProtocolCode angeben. Wenn Sie die Geräteklasse des Geräts kennen, können Sie alternativ den Konstruktor aufrufen, indem Sie eine bestimmte UsbDeviceClasses-Eigenschaft angeben.
Suchen des Geräts – Der grundlegende Weg
Dies ist die einfachste Möglichkeit, ein USB-Gerät zu finden. Weitere Informationen finden Sie unter Schnellstart: Auflisten häufig verwendeter Geräte.
- Übergeben Sie die abgerufene AQS-Zeichenfolge an FindAllAsync. Der Aufruf ruft ein DeviceInformationCollection-Objekt ab.
- Durchlaufen Sie die Auflistung. Jede Iteration ruft ein DeviceInformation-Objekt ab.
- Rufen Sie den Wert der DeviceInformation.Id-Eigenschaft ab. Der Zeichenfolgenwert ist der Pfad des Geräts instance. Beispiel: "\\\\?\\USB#VID_045E&PID_078F#6&1b8ff026&0&5#{dee824ef-729b-4a0e-9c14-b7117d33a817}".
- Rufen Sie FromIdAsync auf, indem Sie das Gerät instance Zeichenfolge übergeben und das UsbDevice-Objekt abrufen. Anschließend können Sie das UsbDevice-Objekt verwenden, um andere Vorgänge auszuführen, z. B. das Senden einer Steuerelementübertragung. Wenn die App die Verwendung des UsbDevice-Objekts abgeschlossen hat, muss die App es durch Aufrufen von Close freigeben. Hinweis Wenn die UWP-App angehalten wird, wird das Gerät automatisch geschlossen. Um die Verwendung eines veralteten Handles für zukünftige Vorgänge zu vermeiden, muss die App den UsbDevice-Verweis freigegeben haben.
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.");
}
}
Suchen des Geräts mithilfe von DeviceWatcher
Alternativ können Sie Geräte dynamisch auflisten. Anschließend kann Ihre App eine Benachrichtigung erhalten, wenn Geräte hinzugefügt oder entfernt werden oder wenn sich die Geräteeigenschaften ändern. Weitere Informationen finden Sie unter Abrufen von Benachrichtigungen, wenn Geräte hinzugefügt, entfernt oder geändert werden.
Ein DeviceWatcher-Objekt ermöglicht es einer App, Geräte dynamisch zu erkennen, wenn sie hinzugefügt und aus dem System entfernt werden.
Erstellen Sie ein DeviceWatcher-Objekt , um zu erkennen, wann das Gerät dem System hinzugefügt oder entfernt wird. Sie müssen das Objekt erstellen, indem Sie CreateWatcher aufrufen und die AQS-Zeichenfolge angeben.
Implementieren und Registrieren von Handlern für hinzugefügte und entfernte Ereignisse für das DeviceWatcher-Objekt . Diese Ereignishandler werden aufgerufen, wenn Geräte (mit den gleichen Identifikationsinformationen) hinzugefügt oder aus dem System entfernt werden.
Starten und beenden Sie das DeviceWatcher-Objekt .
Die App muss das DeviceWatcher-Objekt durch Aufrufen von Start starten, damit sie Geräte erkennen kann, wenn sie dem System hinzugefügt oder entfernt werden. Umgekehrt muss die App den DeviceWatcher beenden, indem sie Stop aufruft, wenn es nicht mehr erforderlich ist, Geräte zu erkennen. Das Beispiel verfügt über zwei Schaltflächen, mit denen der Benutzer DeviceWatcher starten und beenden kann.
In diesem Codebeispiel wird gezeigt, wie Sie eine Geräteüberwachung erstellen und starten, um nach Instanzen des SuperMUTT-Geräts zu suchen.
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();
}
Öffnen des Geräts
Um das Gerät zu öffnen, muss die App einen asynchronen Vorgang starten, indem die statische Methode FromIdAsync aufgerufen und das Gerät instance Pfad übergeben wird (abgerufen von DeviceInformation.Id). Das Ergebnis dieses Vorgangs ist ein UsbDevice-Objekt , das für die zukünftige Kommunikation mit dem Gerät verwendet wird, z. B. für die Durchführung von Datenübertragungen.
Nachdem Sie mit der Verwendung des UsbDevice-Objekts fertig sind, müssen Sie es freigeben. Durch das Freigeben des Objekts werden alle ausstehenden Datenübertragungen abgebrochen. Die Vervollständigungsrückrufroutinen für diese Vorgänge werden weiterhin mit einem abgebrochenen Fehler aufgerufen oder der Vorgang abgeschlossen.
C++-Apps müssen den Verweis mithilfe des löschen-Schlüsselwort (keyword) freigeben. C#/VB-Apps müssen die UsbDevice.Dispose-Methode aufrufen. JavaScript-Apps müssen UsbDevice.Close aufrufen.
FromIdAsync schlägt fehl, wenn das Gerät verwendet wird oder nicht gefunden werden kann.