Start · Sprachen · JavaScript · Referenz · USBDevice.selectAlternateInterface()

USBDevice.selectAlternateInterface()

Methode

Wählt für ein bereits beanspruchtes USB-Interface eine alternative Einstellung (Alternate Setting) aus und gibt ein <code>Promise</code> zurück, das nach dem Umschalten erfüllt wird.

seit JavaScript WebUSB: Chrome/Edge 61+, Opera; nicht in Firefox u Kategorie: webapi

Signatur

USBDevice.prototype.selectAlternateInterface(interfaceNumber, alternateSetting)

Beschreibung

Ein USB-Interface kann mehrere alternative Einstellungen (Alternate Settings) haben. Jede davon hat eigene Endpunkte, zum Beispiel mit anderer Paketgröße, anderer Bandbreite oder einer anderen Übertragungsart. Typische Fälle sind Audio- und Video-Geräte: Einstellung 0 hat meist gar keine Endpunkte und belegt dadurch keine Bandbreite, erst eine höhere Einstellung schaltet die isochronen Datenströme frei. Mit selectAlternateInterface() sendet der Browser den Standard-Befehl SET_INTERFACE an das Gerät.

Die Methode lässt sich nur aufrufen, wenn das Gerät mit open() geöffnet wurde, mit selectConfiguration() eine Konfiguration aktiv ist und das Interface mit claimInterface() beansprucht wurde. Danach enthält USBInterface.alternate die neu gewählte Einstellung. Über deren endpoints sieht man, welche Endpunktnummern man für transferIn(), transferOut() oder isochronousTransferIn() verwenden kann.

Welche Einstellungen es gibt, steht in USBInterface.alternates. Jeder Eintrag ist ein USBAlternateInterface mit alternateSetting, interfaceClass, interfaceSubclass, interfaceProtocol und endpoints.

Parameter

Name Typ Default Beschreibung
$interfaceNumber Pflicht number Nummer des Interfaces (USBInterface.interfaceNumber) in der aktiven Konfiguration. Das Interface muss vorher mit claimInterface() beansprucht worden sein.
$alternateSetting Pflicht number Nummer der gewünschten alternativen Einstellung (USBAlternateInterface.alternateSetting).

Rückgabewert

Typ
Promise<undefined>
Beschreibung
Ein Promise, das ohne Wert erfüllt wird, sobald das Gerät die Einstellung übernommen hat. Es wird abgelehnt, zum Beispiel mit NotFoundError, wenn es das Interface oder die Einstellung nicht gibt, mit InvalidStateError, wenn das Gerät nicht geöffnet oder das Interface nicht beansprucht ist, oder mit NetworkError, wenn die Übertragung fehlschlägt.

Beispiele

Grundablauf: öffnen, beanspruchen, Einstellung wählen

const connect = async () => {
  const device = await navigator.usb.requestDevice({
    filters: [{ vendorId: 0x2341 }]
  });
  await device.open();
  if (device.configuration === null) {
    await device.selectConfiguration(1);
  }
  await device.claimInterface(0);
  // Alternative Einstellung 1 für Interface 0 aktivieren
  await device.selectAlternateInterface(0, 1);

  const iface = device.configuration.interfaces.find(i => i.interfaceNumber === 0);
  console.log('Aktive Einstellung:', iface.alternate.alternateSetting);
  return device;
};

// Muss durch eine Nutzeraktion ausgelöst werden
document.querySelector('#connect').addEventListener('click', connect);
Aktive Einstellung: 1

Passende Einstellung anhand der Endpunkte suchen

const selectIsochronousSetting = async (device, interfaceNumber) => {
  const iface = device.configuration.interfaces
    .find(i => i.interfaceNumber === interfaceNumber);

  // Erste Einstellung mit isochronem IN-Endpunkt suchen
  const alt = iface.alternates.find(a =>
    a.endpoints.some(ep => ep.type === 'isochronous' && ep.direction === 'in')
  );
  if (!alt) throw new Error('Keine isochrone Einstellung vorhanden');

  await device.claimInterface(interfaceNumber);
  await device.selectAlternateInterface(interfaceNumber, alt.alternateSetting);

  const ep = alt.endpoints.find(e => e.direction === 'in');
  console.log(`Einstellung ${alt.alternateSetting}, Endpunkt ${ep.endpointNumber}, ${ep.packetSize} Byte`);
  return ep;
};
Einstellung 2, Endpunkt 1, 1024 Byte

Fehlerbehandlung und Zurückschalten auf Einstellung 0

const stopStream = async (device, interfaceNumber) => {
  try {
    // Einstellung 0 gibt die reservierte Bandbreite wieder frei
    await device.selectAlternateInterface(interfaceNumber, 0);
    await device.releaseInterface(interfaceNumber);
    console.log('Stream gestoppt');
  } catch (err) {
    if (err.name === 'NotFoundError') {
      console.error('Interface oder Einstellung existiert nicht');
    } else if (err.name === 'InvalidStateError') {
      console.error('Gerät nicht geöffnet oder Interface nicht beansprucht');
    } else {
      console.error('USB-Fehler:', err);
    }
  }
};
Stream gestoppt

// Wichtig · Fallstricke

  • Browserunterstützung: WebUSB gibt es nur in Chromium-basierten Browsern (Chrome, Edge, Opera). Firefox und Safari unterstützen die API nicht. Vor der Nutzung 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.
  • Reihenfolge: Wer die Methode vor claimInterface() aufruft, bekommt einen InvalidStateError. Nach dem Umschalten können sich die Endpunkte ändern, deshalb die Endpunktnummern immer aus iface.alternate.endpoints neu lesen.
  • Geschützte Klassen: Interfaces geschützter Klassen wie HID, Massenspeicher, Audio oder Video beansprucht in der Regel schon der Betriebssystem-Treiber. claimInterface() schlägt dann fehl, und damit auch das Umschalten.
  • Laufende Übertragungen auf den Endpunkten der alten Einstellung werden durch das Umschalten abgebrochen.
  • Unter Windows braucht das Gerät passende Treiber (z. B. WinUSB), sonst schlägt der Zugriff fehl.