Start · Sprachen · JavaScript · Referenz · USBInTransferResult

USBInTransferResult

Schnittstelle

Enthält das Ergebnis eines eingehenden USB-Transfers über <code>USBDevice.transferIn()</code> oder <code>controlTransferIn()</code>: die empfangenen Daten und den Status.

seit JavaScript Chromium-Browser (Chrome/Edge/Opera 61+), nur in s Kategorie: webapi

Signatur

interface USBInTransferResult

Beschreibung

USBInTransferResult gehört zur WebUSB API. Ein Objekt dieses Typs bekommst du, wenn das Promise von USBDevice.transferIn() (Bulk- oder Interrupt-Transfer) bzw. USBDevice.controlTransferIn() (Control-Transfer) erfüllt wird. Es bündelt die Daten, die das Gerät zum Host geschickt hat, und den Status des Transfers.

Das Interface hat zwei schreibgeschützte Eigenschaften:

  • data – eine DataView auf die empfangenen Bytes. Ist undefined oder null, wenn keine Daten angekommen sind. Die Länge kann kleiner sein als die angeforderte Länge.
  • status – ein String: "ok" (Transfer erfolgreich), "stall" (das Gerät hat einen Stall gemeldet, der Endpunkt muss mit clearHalt() zurückgesetzt werden) oder "babble" (das Gerät hat mehr Daten geschickt als angefordert).

In der Praxis prüfst du nach jedem Transfer zuerst status und liest die Bytes dann mit den DataView-Methoden wie getUint8() oder getUint16() aus, oder du dekodierst sie mit TextDecoder. Mit new USBInTransferResult(status, data) kannst du auch selbst ein Objekt erzeugen, zum Beispiel für Tests oder Mocks.

Parameter

Name Typ Default Beschreibung
$status Pflicht "ok" | "stall" | "babble" Nur beim Konstruktor new USBInTransferResult(status, data): der Status des Transfers.
$data DataView null Nur beim Konstruktor: die empfangenen Daten als DataView.

Rückgabewert

Typ
USBInTransferResult
Beschreibung
Ein Objekt mit den schreibgeschützten Eigenschaften data (DataView | undefined) und status ("ok" | "stall" | "babble").

Beispiele

Bulk-Daten lesen und Status prüfen

// Muss durch eine Nutzeraktion ausgelöst werden (z. B. Klick)
const connectAndRead = 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);

  // Bis zu 64 Bytes von Endpunkt 1 lesen
  const result = await device.transferIn(1, 64);

  if (result.status === 'ok' && result.data) {
    const text = new TextDecoder().decode(result.data);
    console.log(`Empfangen (${result.data.byteLength} Bytes):`, text);
  } else if (result.status === 'stall') {
    console.warn('Endpunkt blockiert – setze zurück');
    await device.clearHalt('in', 1);
  }
};

document.querySelector('#connect').addEventListener('click', connectAndRead);
Empfangen (12 Bytes): Hello World!

Control-Transfer: Gerätedeskriptor auslesen

const readDeviceDescriptor = async (device) => {
  const result = await device.controlTransferIn({
    requestType: 'standard',
    recipient: 'device',
    request: 0x06,      // GET_DESCRIPTOR
    value: 0x0100,      // Gerätedeskriptor, Index 0
    index: 0x0000
  }, 18);

  if (result.status !== 'ok') {
    throw new Error(`Transfer fehlgeschlagen: ${result.status}`);
  }

  const view = result.data;
  return {
    bcdUSB: view.getUint16(2, true).toString(16),
    vendorId: view.getUint16(8, true).toString(16),
    productId: view.getUint16(10, true).toString(16)
  };
};

// const info = await readDeviceDescriptor(device);
// console.log(info);
{ bcdUSB: '200', vendorId: '2341', productId: '43' }

Ergebnis für Tests selbst erzeugen

const bytes = new Uint8Array([0x01, 0x02, 0xff]);
const fake = new USBInTransferResult('ok', new DataView(bytes.buffer));

console.log(fake.status);            // 'ok'
console.log(fake.data.getUint8(2));  // 255
ok 255

// Wichtig · Fallstricke

  • Kompatibilität: WebUSB gibt es nur in Chromium-Browsern (Chrome, Edge, Opera) auf dem Desktop und in Chrome für Android. Firefox und Safari unterstützen die API nicht. Prüfe deshalb vorher mit 'usb' in navigator, ob sie verfügbar ist.
  • Die API steht nur in sicheren Kontexten (HTTPS oder localhost) zur Verfügung. Du kannst sie per Permissions-Policy (usb) sperren. Außerdem erfordert requestDevice() eine Nutzeraktion.
  • data kann kürzer sein als angefordert. Prüfe immer data.byteLength, bevor du liest, sonst wirft die DataView einen RangeError.
  • Bei "stall" bleibt der Endpunkt blockiert, bis du device.clearHalt('in', endpointNumber) aufrufst. Ein Status "babble" deutet auf einen zu kleinen Puffer oder auf ein fehlerhaftes Gerät hin.
  • Die DataView kann auf einen größeren ArrayBuffer zeigen. Beachte daher byteOffset, wenn du direkt auf data.buffer zugreifst.
  • Mehrbyte-Werte in USB-Deskriptoren sind Little Endian. Übergib deshalb bei getUint16() und ähnlichen Methoden true als zweites Argument.
  • Transportfehler (Gerät getrennt, ungültiger Endpunkt) führen nicht zu einem Status, sondern zu einem abgelehnten Promise mit einer DOMException. Fang sie mit try/catch ab.