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

USBDevice.clearHalt()

Methode

Hebt den Halt-Zustand (Stall) eines USB-Endpunkts auf und gibt ein <code>Promise</code> zurück, das erfüllt wird, sobald der Endpunkt wieder Daten übertragen kann.

seit JavaScript WebUSB: Chrome/Edge 61+, Opera 48+ (kein Firefox, Kategorie: webapi

Signatur

USBDevice.prototype.clearHalt(direction, endpointNumber)

Beschreibung

Die Methode clearHalt() des USBDevice-Interfaces sendet eine Standardanfrage CLEAR_FEATURE(ENDPOINT_HALT) an das Gerät. Dadurch wird ein Bulk- oder Interrupt-Endpunkt aus dem Halt-Zustand geholt. In diesen Zustand gerät ein Endpunkt, wenn das Gerät eine Übertragung mit einem STALL-Handshake ablehnt, z. B. nach einem Protokollfehler oder einem ungültigen Befehl.

Ob ein Endpunkt blockiert ist, erkennen Sie an einem USBInTransferResult oder USBOutTransferResult mit status === "stall", den Sie von transferIn() bzw. transferOut() erhalten. Solange Sie clearHalt() nicht aufrufen, schlagen alle weiteren Übertragungen auf diesem Endpunkt fehl. Rufen Sie die Methode also als Teil Ihrer Fehlerbehandlung auf, bevor Sie es erneut versuchen.

Voraussetzung: Das Gerät muss mit open() geöffnet sein, eine Konfiguration muss aktiv sein, und die Schnittstelle, zu der der Endpunkt gehört, muss mit claimInterface() belegt sein. Bei Control-Transfers (Endpunkt 0) brauchen Sie clearHalt() nicht, denn ein Stall dort wird beim nächsten Setup-Paket automatisch aufgehoben.

Parameter

Name Typ Default Beschreibung
$direction Pflicht "in" | "out" Richtung des Endpunkts: "in" (Gerät → Host) oder "out" (Host → Gerät).
$endpointNumber Pflicht number Nummer des Endpunkts (1–15) ohne Richtungsbit, also z. B. 1 statt 0x81. Sie entspricht USBEndpoint.endpointNumber.

Rückgabewert

Typ
Promise<undefined>
Beschreibung
Ein Promise, das ohne Wert erfüllt wird, sobald der Halt-Zustand aufgehoben ist. Es wird mit einer DOMException abgelehnt, z. B. mit InvalidStateError (Gerät nicht geöffnet oder Schnittstelle nicht belegt), NotFoundError (Endpunkt existiert nicht) oder NetworkError (Gerät getrennt oder Übertragung fehlgeschlagen).

Beispiele

Stall beim Lesen erkennen und aufheben

const readWithRecovery = async (device, endpoint = 1, length = 64) => {
  let result = await device.transferIn(endpoint, length);

  if (result.status === 'stall') {
    console.warn('Endpunkt blockiert – hebe Halt auf …');
    await device.clearHalt('in', endpoint);
    // Zweiter Versuch nach dem Zurücksetzen
    result = await device.transferIn(endpoint, length);
  }

  return result;
};

const [device] = await navigator.usb.getDevices();
await device.open();
if (device.configuration === null) await device.selectConfiguration(1);
await device.claimInterface(0);

const res = await readWithRecovery(device);
console.log(res.status, res.data?.byteLength);
Endpunkt blockiert – hebe Halt auf … ok 64

Endpunkte aus dem Deskriptor ermitteln und alle zurücksetzen

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

  for (const ep of iface.alternate.endpoints) {
    if (ep.type === 'bulk' || ep.type === 'interrupt') {
      await device.clearHalt(ep.direction, ep.endpointNumber);
      console.log(`Endpunkt ${ep.endpointNumber} (${ep.direction}) freigegeben`);
    }
  }
};

const device = await navigator.usb.requestDevice({ filters: [{ vendorId: 0x2341 }] });
await device.open();
await device.selectConfiguration(1);
await device.claimInterface(0);
await resetAllEndpoints(device, 0);
Endpunkt 1 (in) freigegeben Endpunkt 2 (out) freigegeben

Schreiben mit Fehlerbehandlung

const sendCommand = async (device, endpoint, bytes) => {
  try {
    const result = await device.transferOut(endpoint, new Uint8Array(bytes));
    if (result.status === 'stall') {
      await device.clearHalt('out', endpoint);
      throw new Error('Gerät hat den Befehl abgelehnt (STALL)');
    }
    return result.bytesWritten;
  } catch (err) {
    console.error('USB-Fehler:', err.name ?? '', err.message);
    return 0;
  }
};

const written = await sendCommand(device, 2, [0x01, 0xff]);
console.log('Geschrieben:', written);
Geschrieben: 2

// Wichtig · Fallstricke

  • Browser-Kompatibilität: WebUSB gibt es nur in Chromium-basierten Browsern (Chrome, Edge, Opera), und das nur auf Desktop und Android. Firefox und Safari unterstützen es nicht. Prüfen Sie die Unterstützung vorher mit 'usb' in navigator.
  • Die API steht nur in einem sicheren Kontext (HTTPS oder localhost) zur Verfügung. In iframes kann die Permissions Policy usb sie sperren.
  • Häufiger Fehler: Wer als endpointNumber die Endpunktadresse mit Richtungsbit übergibt (z. B. 0x81), bekommt einen Fehler. Übergeben Sie nur die Nummer und die Richtung getrennt.
  • Nach clearHalt() setzt das Gerät das Data-Toggle-Bit des Endpunkts zurück. Manche Geräte verlangen zusätzlich einen protokollspezifischen Reset, z. B. Bulk-Only Mass Storage Reset, bevor der Endpunkt wieder zuverlässig funktioniert.
  • Rufen Sie clearHalt() nicht in einer Endlosschleife auf. Wenn der Stall immer wieder auftritt, liegt meist ein Protokollfehler vor, z. B. ein ungültiger Befehl oder eine falsche Paketgröße.