Start · Sprachen · JavaScript · Referenz · USBIsochronousOutTransferResult

USBIsochronousOutTransferResult

Schnittstelle

Enthält das Ergebnis von <code>USBDevice.isochronousTransferOut()</code>: ein Array von Paketen mit Status und Anzahl der geschriebenen Bytes je Paket.

seit JavaScript Chrome/Edge 61+, Opera 48+ (experimentell, nicht i Kategorie: webapi

Signatur

interface USBIsochronousOutTransferResult

Beschreibung

USBIsochronousOutTransferResult gehört zur WebUSB-API. Ein Objekt dieses Typs erhalten Sie, wenn das von USBDevice.isochronousTransferOut(endpointNumber, data, packetLengths) zurückgegebene Promise erfüllt wird. Isochrone Übertragungen nutzt man für zeitkritische Datenströme mit fester Bandbreite, etwa Audio- oder Videodaten an USB-Soundkarten, DACs oder Kameras. Bei dieser Übertragungsart ist die Einhaltung des Zeitplans wichtiger als eine garantierte Zustellung.

Das Interface hat nur eine Eigenschaft: packets. Sie ist ein schreibgeschütztes Array aus USBIsochronousOutTransferPacket-Objekten. Für jeden Eintrag in packetLengths gibt es darin genau ein Paket. Jedes Paket hat folgende Eigenschaften:

  • bytesWritten: die Anzahl der Bytes, die tatsächlich an das Gerät gesendet wurden.
  • status: "ok" bei Erfolg oder "stall", wenn der Endpunkt blockiert hat (Stall).

Weil isochrone Übertragungen keine Wiederholung bei Fehlern kennen, sollten Sie nach jedem Transfer die Pakete einzeln prüfen. Anders als bei transferOut() gibt es kein Gesamtergebnis. Ob einzelne Pakete fehlgeschlagen sind, erfahren Sie nur über den Status des jeweiligen Pakets.

Über den Konstruktor new USBIsochronousOutTransferResult(packets) können Sie Ergebnisobjekte auch selbst erzeugen. Das ist vor allem für Tests und Mocks nützlich.

Parameter

Name Typ Default Beschreibung
$packets Pflicht USBIsochronousOutTransferPacket[] Nur beim Konstruktor: ein Array von USBIsochronousOutTransferPacket-Objekten, die das Ergebnisobjekt enthalten soll.

Rückgabewert

Typ
USBIsochronousOutTransferResult
Beschreibung
Ein Objekt mit der schreibgeschützten Eigenschaft packets (Array von USBIsochronousOutTransferPacket). Jedes Paket hat die Eigenschaften bytesWritten (number) und status ("ok" | "stall").

Beispiele

Audiodaten isochron senden und Pakete auswerten

// Muss durch eine Nutzeraktion ausgelöst werden (z. B. Klick)
const sendAudioFrame = async () => {
  const [device] = await navigator.usb.getDevices();
  await device.open();
  await device.selectConfiguration(1);
  await device.claimInterface(1);
  await device.selectAlternateInterface(1, 1); // Alternate-Setting mit Bandbreite

  const packetLengths = [192, 192, 192, 192]; // 4 Pakete à 192 Byte
  const data = new Uint8Array(packetLengths.reduce((a, b) => a + b, 0));

  const result = await device.isochronousTransferOut(1, data, packetLengths);

  result.packets.forEach((packet, i) => {
    console.log(`Paket ${i}: ${packet.status}, ${packet.bytesWritten} Byte`);
  });
};

document.querySelector('#play').addEventListener('click', sendAudioFrame);
Paket 0: ok, 192 Byte Paket 1: ok, 192 Byte Paket 2: ok, 192 Byte Paket 3: ok, 192 Byte

Übertragungsstatistik aus dem Ergebnis berechnen

const summarize = (result) => {
  const total = result.packets.reduce((sum, p) => sum + p.bytesWritten, 0);
  const stalled = result.packets.filter((p) => p.status === 'stall').length;
  return { pakete: result.packets.length, bytes: total, stalls: stalled };
};

// Innerhalb einer async-Funktion:
// const result = await device.isochronousTransferOut(1, data, packetLengths);
// console.log(summarize(result));
{ pakete: 4, bytes: 768, stalls: 0 }

Ergebnisobjekt für Unit-Tests selbst erzeugen

const packets = [
  new USBIsochronousOutTransferPacket('ok', 192),
  new USBIsochronousOutTransferPacket('stall', 0)
];
const fakeResult = new USBIsochronousOutTransferResult(packets);

console.log(fakeResult.packets.length);
console.log(fakeResult.packets[1].status);
2 stall

Nach einem Stall den Endpunkt zurücksetzen

const sendWithRecovery = async (device, endpoint, data, lengths) => {
  const result = await device.isochronousTransferOut(endpoint, data, lengths);
  if (result.packets.some((p) => p.status === 'stall')) {
    console.warn('Stall erkannt – Endpunkt wird zurückgesetzt');
    await device.clearHalt('out', endpoint);
  }
  return result;
};

// Wichtig · Fallstricke

  • Kompatibilität: WebUSB ist experimentell. Die API gibt es nur in Chromium-basierten Browsern (Chrome, Edge, Opera) auf dem Desktop und unter Android. Firefox und Safari unterstützen sie nicht. Prüfen Sie die Verfügbarkeit mit 'usb' in navigator.
  • Sicherer Kontext: WebUSB funktioniert nur über HTTPS oder localhost. Der Zugriff auf ein Gerät setzt voraus, dass der Nutzer es vorher über navigator.usb.requestDevice() ausgewählt hat. Dieser Aufruf muss durch eine Nutzeraktion ausgelöst werden. Die Berechtigungsrichtlinie usb kann WebUSB in iframes sperren.
  • Kein Fehler bei Paketverlust: Das Promise wird auch dann erfüllt, wenn einzelne Pakete mit "stall" enden. Prüfen Sie deshalb immer jedes Paket in packets einzeln.
  • Die Summe aller Werte in packetLengths muss genau der Länge von data entsprechen. Sonst wird das Promise mit einem Fehler abgelehnt.
  • Isochrone Endpunkte sind oft erst nach selectAlternateInterface() aktiv, weil das Standard-Setting (0) meist keine Bandbreite reserviert.
  • Manche Geräteklassen, z. B. USB-Audio, beansprucht das Betriebssystem selbst. Solche Interfaces lassen sich dann nicht über claimInterface() belegen.