Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2bf67e05 authored by Jackeagle's avatar Jackeagle
Browse files

Fix Volla Tablet unlock: use reactive clearHalt instead of proactive



Proactive clearHalt on open() sends CLEAR_FEATURE(ENDPOINT_HALT) even
when endpoints are not halted. This corrupts the MediaTek bootloader's
USB state on Volla Tablet, causing flashing unlock to never receive a
response. Replace with reactive approach: detect stall status on actual
transfers and clearHalt + retry only when needed. This still fixes
Murena Two stale endpoints from interrupted sessions.

Signed-off-by: default avatarJackeagle <jackeagle102@gmail.com>
parent fe2840ea
Loading
Loading
Loading
Loading
+18 −17
Original line number Diff line number Diff line
@@ -115,21 +115,6 @@ export class WebUsbTransport {
        );
      }

      // Clear any stale halt condition on both endpoints.
      // Previous sessions that were interrupted (tab closed, USB unplugged)
      // can leave endpoints in a HALTED state, causing every subsequent
      // transferIn/transferOut to fail with "A transfer error has occurred".
      try {
        await this._device.clearHalt("in", this._inEndpoint);
      } catch {
        // clearHalt may fail if endpoint isn't halted — that's fine
      }
      try {
        await this._device.clearHalt("out", this._outEndpoint);
      } catch {
        // clearHalt may fail if endpoint isn't halted — that's fine
      }

      this._rxBuf = new Uint8Array(0);
      this._opened = true;
      log(
@@ -221,7 +206,15 @@ export class WebUsbTransport {
      throw new UsbError("Transport not open");
    }

    const result = await this._device.transferOut(this._outEndpoint, data as BufferSource);
    let result = await this._device.transferOut(this._outEndpoint, data as BufferSource);

    // Stalled endpoint from a previous interrupted session — clear and retry
    if (result.status === "stall") {
      log("OUT endpoint stalled, clearing halt and retrying...");
      await this._device.clearHalt("out", this._outEndpoint);
      result = await this._device.transferOut(this._outEndpoint, data as BufferSource);
    }

    if (result.status !== "ok") {
      throw new UsbError(`USB transferOut failed: status=${result.status}`);
    }
@@ -386,7 +379,15 @@ export class WebUsbTransport {
  private async doTransferIn(
    bufferSize: number = USB_RECEIVE_BUFFER_SIZE,
  ): Promise<Uint8Array> {
    const result = await this._device.transferIn(this._inEndpoint, bufferSize);
    let result = await this._device.transferIn(this._inEndpoint, bufferSize);

    // Stalled endpoint from a previous interrupted session — clear and retry
    if (result.status === "stall") {
      log("IN endpoint stalled, clearing halt and retrying...");
      await this._device.clearHalt("in", this._inEndpoint);
      result = await this._device.transferIn(this._inEndpoint, bufferSize);
    }

    if (result.status !== "ok") {
      throw new UsbError(`USB transferIn failed: status=${result.status}`);
    }