Start · Sprachen · JavaScript · Referenz · USBIsochronousInTransferPacket

USBIsochronousInTransferPacket

Schnittstelle

Steht für ein einzelnes Paket einer isochronen Eingangsübertragung der WebUSB API und enthält dessen Daten (<code>data</code>) und Status (<code>status</code>).

seit JavaScript Chrome/Edge 61+ (experimentell, nur Chromium-Brows Kategorie: webapi

Signatur

interface USBIsochronousInTransferPacket

Beschreibung

Das Interface USBIsochronousInTransferPacket gehört zur WebUSB API. Es beschreibt ein einzelnes Paket einer isochronen Eingangsübertragung, also einer Übertragung vom Gerät zum Host. Solche Pakete bekommst du nicht direkt, sondern über das Array packets des USBIsochronousInTransferResult-Objekts. Dieses Objekt liefert das Promise von USBDevice.isochronousTransferIn().

Isochrone Übertragungen nutzt man für zeitkritische Datenströme mit fester Bandbreite, zum Beispiel für USB-Audio, Webcams oder Messgeräte. Eine Fehlerkorrektur durch erneutes Senden gibt es dabei nicht. Deshalb hat jedes Paket einen eigenen Status. Einzelne Pakete können fehlschlagen, ohne dass die ganze Übertragung abbricht.

Eigenschaften (nur lesbar):

  • data: ein DataView mit den tatsächlich empfangenen Bytes dieses Pakets. Er kann kürzer sein als die angeforderte Paketlänge.
  • status: ein String mit dem Paketstatus. "ok" heißt erfolgreich, "stall" heißt, der Endpunkt meldet einen Stall-Fehler, und "babble" heißt, das Gerät hat mehr Daten gesendet als erwartet.

Mit dem Konstruktor new USBIsochronousInTransferPacket(status, data) kannst du Pakete auch selbst erzeugen. Das ist vor allem für Tests, Mocks oder eigene USB-Implementierungen nützlich.

Parameter

Name Typ Default Beschreibung
$status Pflicht "ok" | "stall" | "babble" Nur Konstruktor: der Status des Pakets.
$data DataView null Nur Konstruktor: die Nutzdaten des Pakets als DataView.

Rückgabewert

Typ
USBIsochronousInTransferPacket
Beschreibung
Ein Paketobjekt mit den nur lesbaren Eigenschaften data (DataView) und status (string).

Beispiele

Paket manuell erzeugen (z. B. für Tests)

const bytes = new Uint8Array([0x10, 0x20, 0x30, 0x40]);
const packet = new USBIsochronousInTransferPacket('ok', new DataView(bytes.buffer));

console.log(packet.status);
console.log(packet.data.byteLength);
console.log(packet.data.getUint8(1));
ok 4 32

Audiodaten von einem USB-Gerät isochron lesen

const readAudioFrames = async () => {
  const device = await navigator.usb.requestDevice({ filters: [{ vendorId: 0x1234 }] });
  await device.open();
  await device.selectConfiguration(1);
  await device.claimInterface(1);
  await device.selectAlternateInterface(1, 1);

  // 8 Pakete mit je bis zu 192 Bytes von Endpunkt 1 anfordern
  const packetLengths = new Array(8).fill(192);
  const result = await device.isochronousTransferIn(1, packetLengths);

  const chunks = [];
  for (const packet of result.packets) {
    if (packet.status === 'ok') {
      chunks.push(new Uint8Array(packet.data.buffer, packet.data.byteOffset, packet.data.byteLength));
    }
  }
  console.log(`Gültige Pakete: ${chunks.length} von ${result.packets.length}`);
  return chunks;
};

document.querySelector('#start').addEventListener('click', readAudioFrames);
Gültige Pakete: 8 von 8

Paketstatus auswerten und Fehler zählen

const summarize = (packets) =>
  packets.reduce((stats, { status, data }) => {
    stats[status] = (stats[status] ?? 0) + 1;
    if (status === 'ok') stats.bytes += data.byteLength;
    return stats;
  }, { bytes: 0 });

const packets = [
  new USBIsochronousInTransferPacket('ok', new DataView(new ArrayBuffer(192))),
  new USBIsochronousInTransferPacket('babble', new DataView(new ArrayBuffer(0))),
  new USBIsochronousInTransferPacket('ok', new DataView(new ArrayBuffer(100)))
];

console.log(summarize(packets));
{ bytes: 292, ok: 2, babble: 1 }

// Wichtig · Fallstricke

  • Browser-Kompatibilität: WebUSB ist experimentell und gibt es nur in Chromium-Browsern (Chrome, Edge, Opera, Chrome für Android). Firefox und Safari unterstützen die API nicht. Prüfe die Unterstützung vorher mit 'usb' in navigator.
  • Die API funktioniert nur in einem sicheren Kontext (HTTPS). Der erste Gerätezugriff über requestDevice() braucht eine Benutzeraktion, zum Beispiel einen Klick. Außerdem kann eine Permissions Policy (usb) den Zugriff in iframes sperren.
  • packet.data kann kürzer sein als die angeforderte Länge in packetLengths. Verlass dich also immer auf data.byteLength. Die einzelnen DataViews zeigen in der Regel auf Bereiche von result.data. Zwischen den Paketen können dort Lücken liegen, deshalb solltest du result.data nicht einfach am Stück auswerten.
  • Isochrone Übertragungen senden verlorene oder fehlerhafte Daten nicht erneut. Bei "stall" musst du den Endpunkt gegebenenfalls mit clearHalt() zurücksetzen. Bei "babble" sind die Daten des Pakets unbrauchbar.
  • Auf manchen Betriebssystemen (vor allem Windows) sind für den Zugriff passende Treiber nötig, zum Beispiel WinUSB. Geräteklassen, die das System selbst belegt (etwa Audio oder HID), sind oft gesperrt.