Start · Sprachen · JavaScript · Referenz · USBInterface

USBInterface

Schnittstelle

Beschreibt eine Schnittstelle einer USB-Konfiguration: Nummer, aktive und mögliche Alternativeinstellungen und ob sie gerade von der Seite belegt ist.

seit JavaScript Chromium 61+ (Chrome, Edge, Opera); nicht in Firef Kategorie: webapi

Signatur

interface USBInterface

Beschreibung

USBInterface gehört zur WebUSB API und beschreibt eine einzelne Schnittstelle (Interface) innerhalb einer USBConfiguration eines Geräts. Ein USB-Gerät kann mehrere Schnittstellen anbieten, zum Beispiel eine für Daten und eine für Steuerbefehle oder Firmware-Updates. Jede Schnittstelle hat eigene Endpunkte, über die Daten fließen.

Man bekommt USBInterface-Objekte meistens über device.configuration.interfaces oder device.configurations[n].interfaces. Die wichtigsten Eigenschaften:

  • interfaceNumber: Nummer der Schnittstelle (bInterfaceNumber), die man an USBDevice.claimInterface() übergibt.
  • alternate: die gerade aktive USBAlternateInterface mit Klasse, Unterklasse, Protokoll und Endpunkten.
  • alternates: ein Array mit allen möglichen Alternativeinstellungen.
  • claimed: true, wenn die Seite die Schnittstelle gerade über claimInterface() belegt hat.

Vor jedem Datentransfer (transferIn(), transferOut(), isochronousTransferIn() …) muss die passende Schnittstelle belegt werden. Mit USBInterface findet man vorher heraus, welche Schnittstelle die richtige ist, meist anhand von alternate.interfaceClass (z. B. 0xFF für herstellerspezifisch) und den Endpunkt-Richtungen.

Einen Konstruktor gibt es auch (new USBInterface(configuration, interfaceNumber)). In der Praxis braucht man ihn aber kaum, weil der Browser die Objekte selbst anlegt.

Parameter

Name Typ Default Beschreibung
$configuration Pflicht USBConfiguration Nur beim Konstruktor: die Konfiguration, zu der die Schnittstelle gehört.
$interfaceNumber Pflicht number Nur beim Konstruktor: Nummer der Schnittstelle innerhalb der Konfiguration. Gibt es die Nummer nicht, wird ein RangeError geworfen.

Rückgabewert

Typ
USBInterface
Beschreibung
Ein Objekt mit den schreibgeschützten Eigenschaften interfaceNumber (number), alternate (USBAlternateInterface), alternates (USBAlternateInterface[]) und claimed (boolean).

Beispiele

Schnittstellen eines Geräts auflisten

// Muss durch eine Nutzeraktion ausgelöst werden (z. B. Klick)
document.querySelector('#connect').addEventListener('click', async () => {
  const device = await navigator.usb.requestDevice({ filters: [{ vendorId: 0x2341 }] });
  await device.open();
  if (device.configuration === null) {
    await device.selectConfiguration(1);
  }

  for (const iface of device.configuration.interfaces) {
    const alt = iface.alternate;
    console.log(
      `Interface ${iface.interfaceNumber}: Klasse 0x${alt.interfaceClass.toString(16)}, ` +
      `${alt.endpoints.length} Endpunkte, ${iface.alternates.length} Alternativen, belegt: ${iface.claimed}`
    );
  }
});
Interface 0: Klasse 0x2, 1 Endpunkte, 1 Alternativen, belegt: false Interface 1: Klasse 0xa, 2 Endpunkte, 1 Alternativen, belegt: false Interface 2: Klasse 0xff, 2 Endpunkte, 1 Alternativen, belegt: false

Herstellerspezifische Schnittstelle finden, belegen und Daten senden

const connectVendorInterface = async (device) => {
  await device.open();
  if (device.configuration === null) await device.selectConfiguration(1);

  // Schnittstelle mit Klasse 0xFF (herstellerspezifisch) suchen
  const iface = device.configuration.interfaces.find(
    (i) => i.alternates.some((a) => a.interfaceClass === 0xff)
  );
  if (!iface) throw new Error('Keine passende Schnittstelle gefunden');

  await device.claimInterface(iface.interfaceNumber);
  console.log('Belegt:', iface.claimed);

  const outEndpoint = iface.alternate.endpoints.find((e) => e.direction === 'out');
  const data = new TextEncoder().encode('LED ON');
  const result = await device.transferOut(outEndpoint.endpointNumber, data);
  console.log('Gesendet:', result.bytesWritten, 'Bytes');

  await device.releaseInterface(iface.interfaceNumber);
  console.log('Belegt:', iface.claimed);
};
Belegt: true Gesendet: 6 Bytes Belegt: false

Alternativeinstellung wechseln

const selectBestAlternate = async (device, iface) => {
  await device.claimInterface(iface.interfaceNumber);

  // Die Alternative mit den meisten Endpunkten wählen
  const best = iface.alternates.reduce((a, b) =>
    b.endpoints.length > a.endpoints.length ? b : a
  );
  await device.selectAlternateInterface(iface.interfaceNumber, best.alternateSetting);

  console.log('Aktive Alternative:', iface.alternate.alternateSetting);
};
Aktive Alternative: 1

Konstruktor direkt verwenden

// Selten nötig: Objekt für eine bekannte Schnittstellennummer erzeugen
const [device] = await navigator.usb.getDevices();
await device.open();
const iface = new USBInterface(device.configuration, 0);
console.log(iface.interfaceNumber, iface.alternates.length);
0 1

// Wichtig · Fallstricke

  • Browser-Unterstützung: WebUSB gibt es nur in Chromium-Browsern (Chrome, Edge, Opera, außerdem Chrome für Android). Firefox und Safari unterstützen die API nicht. Vorher mit 'usb' in navigator prüfen.
  • Sicherer Kontext: Die API funktioniert nur über HTTPS oder localhost. In iframes muss die Permissions Policy usb erlaubt sein.
  • Geschützte Klassen: Schnittstellen mit geschützten Klassen wie HID, Massenspeicher, Audio, Video oder Smartcard lassen sich nicht belegen. claimInterface() wirft dann einen SecurityError. Für HID-Geräte gibt es stattdessen die WebHID API.
  • Treiberkonflikte: Hat das Betriebssystem schon einen Treiber an die Schnittstelle gebunden (z. B. CDC-ACM unter Linux oder ein Windows-Treiber ohne WinUSB), schlägt claimInterface() mit NetworkError fehl.
  • device.configuration ist null, solange keine Konfiguration gewählt wurde. Dann zuerst selectConfiguration() aufrufen.
  • alternate ist eine Live-Ansicht: Nach selectAlternateInterface() zeigt die Eigenschaft die neue Einstellung. Endpunkt-Nummern deshalb nach dem Wechsel neu auslesen.
  • Schnittstellen nach der Nutzung mit releaseInterface() freigeben und das Gerät mit close() schließen, sonst bleiben sie für andere Tabs blockiert.