Start · Sprachen · JavaScript · Referenz · USBEndpoint

USBEndpoint

Schnittstelle

Beschreibt einen Endpunkt eines USB-Geräts (Nummer, Richtung, Übertragungsart, Paketgröße), über den mit <code>transferIn()</code>/<code>transferOut()</code> Daten fließen.

seit JavaScript Chrome/Edge 61+, Opera 48+ (experimentell, nur sic Kategorie: webapi

Signatur

interface USBEndpoint

Beschreibung

Ein Endpunkt ist bei USB der eigentliche Datenkanal zwischen Host und Gerät. Das Interface USBEndpoint der WebUSB API liefert die Metadaten eines solchen Endpunkts. Instanzen bekommt man in der Regel über USBAlternateInterface.endpoints, also z. B. über device.configuration.interfaces[i].alternate.endpoints.

Alle Eigenschaften sind schreibgeschützt:

  • endpointNumber – Nummer des Endpunkts (1–15). Diesen Wert übergibt man an USBDevice.transferIn(), transferOut(), isochronousTransferIn()/Out() und clearHalt().
  • direction – "in" (Gerät → Host) oder "out" (Host → Gerät).
  • type – Übertragungsart: "bulk", "interrupt" oder "isochronous".
  • packetSize – maximale Paketgröße in Byte, die der Endpunkt pro Paket übertragen kann.

Typischer Einsatz: Nach claimInterface() sucht man die passenden IN- und OUT-Endpunkte heraus, statt Endpunktnummern hart zu kodieren. So funktioniert der Code auch mit Geräte-Revisionen, deren Deskriptoren leicht abweichen. Der Kontrollendpunkt 0 taucht dabei nicht in der Liste auf – er wird über controlTransferIn()/controlTransferOut() angesprochen.

Parameter

Name Typ Default Beschreibung
$alternate Pflicht USBAlternateInterface Nur beim Konstruktor new USBEndpoint(alternate, endpointNumber, direction): die alternative Schnittstelle, zu der der Endpunkt gehört.
$endpointNumber Pflicht number Nur beim Konstruktor: Nummer des Endpunkts, der in der alternativen Schnittstelle existieren muss.
$direction Pflicht "in" | "out" Nur beim Konstruktor: Übertragungsrichtung des gesuchten Endpunkts.

Rückgabewert

Typ
USBEndpoint
Beschreibung
Ein Objekt mit den schreibgeschützten Eigenschaften endpointNumber, direction, type und packetSize. Existiert der Endpunkt beim Konstruktor-Aufruf nicht, wird ein RangeError geworfen.

Beispiele

Alle Endpunkte eines Geräts auflisten

// Muss durch eine Nutzergeste (z. B. Klick) ausgelöst werden
const button = document.querySelector('#connect');

button.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) {
    for (const ep of iface.alternate.endpoints) {
      console.log(`Interface ${iface.interfaceNumber}: EP ${ep.endpointNumber} ${ep.direction} ${ep.type} (${ep.packetSize} Byte)`);
    }
  }
});
Interface 0: EP 1 in interrupt (16 Byte) Interface 1: EP 2 out bulk (64 Byte) Interface 1: EP 3 in bulk (64 Byte)

Bulk-Endpunkte dynamisch finden und nutzen

const findBulkEndpoints = (iface) => {
  const eps = iface.alternate.endpoints;
  const inEp = eps.find((ep) => ep.type === 'bulk' && ep.direction === 'in');
  const outEp = eps.find((ep) => ep.type === 'bulk' && ep.direction === 'out');
  if (!inEp || !outEp) throw new Error('Keine Bulk-Endpunkte gefunden');
  return { inEp, outEp };
};

const sendCommand = async (device, ifaceNumber, text) => {
  await device.claimInterface(ifaceNumber);
  const iface = device.configuration.interfaces.find((i) => i.interfaceNumber === ifaceNumber);
  const { inEp, outEp } = findBulkEndpoints(iface);

  await device.transferOut(outEp.endpointNumber, new TextEncoder().encode(text));
  // Mindestens packetSize anfordern, sonst droht ein Babble-Fehler
  const result = await device.transferIn(inEp.endpointNumber, inEp.packetSize);
  return new TextDecoder().decode(result.data);
};

Endpunkt per Konstruktor abfragen

const getEndpoint = (device, ifaceIndex, number, direction) => {
  const alternate = device.configuration.interfaces[ifaceIndex].alternate;
  try {
    return new USBEndpoint(alternate, number, direction);
  } catch (err) {
    console.warn(`Endpunkt ${number}/${direction} existiert nicht:`, err.name);
    return null;
  }
};

// const ep = getEndpoint(device, 1, 2, 'out');
// console.log(ep?.type, ep?.packetSize);
bulk 64

// Wichtig · Fallstricke

Browser-Kompatibilität: WebUSB ist experimentell und nur in Chromium-Browsern (Chrome, Edge, Opera) auf dem Desktop sowie Chrome für Android verfügbar. Firefox und Safari unterstützen die API nicht. Per Feature-Erkennung mit 'usb' in navigator prüfen.

  • Nur in einem sicheren Kontext (HTTPS oder localhost) verfügbar. Zudem lässt sich die API per Permissions-Policy: usb einschränken; in Web Workern gibt es sie nur in Chromium ab Version 96 und nur eingeschränkt.
  • Die Endpunktliste hängt von der aktuell gewählten alternativen Einstellung ab. Nach selectAlternateInterface() können sich Endpunkte ändern, deshalb danach neu auslesen.
  • Bei transferIn() sollte die angeforderte Länge ein Vielfaches von packetSize sein. Kleinere Puffer können zum Status "babble" führen.
  • Endpunkte zu Klassen, die das Betriebssystem schützt (z. B. HID-Tastaturen, Massenspeicher), sind gesperrt. claimInterface() schlägt dann fehl.
  • Bei Status "stall" muss man den Endpunkt mit device.clearHalt(direction, endpointNumber) zurücksetzen.