|
1 | 1 | import { ESPError } from "./types/error.js"; |
2 | 2 | import { Data, deflate, Inflate } from "pako"; |
3 | | -import { Transport, SerialOptions } from "./webserial.js"; |
| 3 | +import { |
| 4 | + Transport, |
| 5 | + SerialOptions, |
| 6 | + ESPRESSIF_VID as ESPRESSIF_USB_VID, |
| 7 | + USB_JTAG_SERIAL_PID as ESPRESSIF_USB_JTAG_SERIAL_PID, |
| 8 | +} from "./webserial.js"; |
4 | 9 | import { ROM } from "./targets/rom.js"; |
5 | 10 | import { ClassicReset, CustomReset, HardReset, ResetConstructors, ResetStrategy, UsbJtagSerialReset } from "./reset.js"; |
6 | 11 | import { getStubJsonByChipName } from "./stubFlasher.js"; |
@@ -159,7 +164,8 @@ export class ESPLoader { |
159 | 164 | 0x3a: "64MB", |
160 | 165 | }; |
161 | 166 |
|
162 | | - USB_JTAG_SERIAL_PID = 0x1001; |
| 167 | + ESPRESSIF_VID = ESPRESSIF_USB_VID; |
| 168 | + USB_JTAG_SERIAL_PID = ESPRESSIF_USB_JTAG_SERIAL_PID; |
163 | 169 |
|
164 | 170 | chip!: ROM; |
165 | 171 | IS_STUB: boolean; |
@@ -585,6 +591,71 @@ export class ESPLoader { |
585 | 591 | return lastError; |
586 | 592 | } |
587 | 593 |
|
| 594 | + /** |
| 595 | + * True if the host sees this port as Espressif USB Serial/JTAG (VID/PID match). |
| 596 | + * Falls back to the chip UARTDEV_BUF_NO helper when Web Serial omits IDs |
| 597 | + * or the USB product ID was customized. |
| 598 | + */ |
| 599 | + async usesUsbJtagSerial(): Promise<boolean> { |
| 600 | + const vid = this.transport.getVid(); |
| 601 | + const pid = this.transport.getPid(); |
| 602 | + if (vid === this.ESPRESSIF_VID && pid === this.USB_JTAG_SERIAL_PID) { |
| 603 | + return true; |
| 604 | + } |
| 605 | + if (vid === this.ESPRESSIF_VID && pid === this.chip.IMAGE_CHIP_ID) { |
| 606 | + return false; |
| 607 | + } |
| 608 | + if (vid !== undefined && vid !== this.ESPRESSIF_VID) { |
| 609 | + return false; |
| 610 | + } |
| 611 | + if (typeof this.chip.usesUsbJtagSerial === "function") { |
| 612 | + return await this.chip.usesUsbJtagSerial(this); |
| 613 | + } |
| 614 | + return false; |
| 615 | + } |
| 616 | + |
| 617 | + /** |
| 618 | + * True if the host sees this port as Espressif USB-OTG (VID/PID match). |
| 619 | + * Falls back to the chip UARTDEV_BUF_NO helper when Web Serial omits IDs |
| 620 | + * or the USB product ID was customized. |
| 621 | + */ |
| 622 | + async usesUsbOtg(): Promise<boolean> { |
| 623 | + const vid = this.transport.getVid(); |
| 624 | + const pid = this.transport.getPid(); |
| 625 | + if (vid === this.ESPRESSIF_VID && this.chip.IMAGE_CHIP_ID != null && pid === this.chip.IMAGE_CHIP_ID) { |
| 626 | + return true; |
| 627 | + } |
| 628 | + if (vid === this.ESPRESSIF_VID && pid === this.USB_JTAG_SERIAL_PID) { |
| 629 | + return false; |
| 630 | + } |
| 631 | + if (vid !== undefined && vid !== this.ESPRESSIF_VID) { |
| 632 | + return false; |
| 633 | + } |
| 634 | + if (typeof this.chip.usesUsbOtg === "function") { |
| 635 | + return await this.chip.usesUsbOtg(this); |
| 636 | + } |
| 637 | + if (typeof this.chip.usingUsbOtg === "function") { |
| 638 | + return await this.chip.usingUsbOtg(this); |
| 639 | + } |
| 640 | + return false; |
| 641 | + } |
| 642 | + |
| 643 | + /** |
| 644 | + * Cap FLASH_WRITE_SIZE to USB_RAM_BLOCK when the stub is talking over |
| 645 | + * USB-OTG. Matches esptool.py's stub USB buffer limit; USB-Serial/JTAG |
| 646 | + * and USB-UART bridges keep the 16 KB default. |
| 647 | + */ |
| 648 | + private async applyUsbFlashWriteSize() { |
| 649 | + const usbRamBlock = this.chip.USB_RAM_BLOCK; |
| 650 | + if (!usbRamBlock) { |
| 651 | + return; |
| 652 | + } |
| 653 | + if (await this.usesUsbOtg()) { |
| 654 | + this.FLASH_WRITE_SIZE = usbRamBlock; |
| 655 | + this.debug(`Using USB_RAM_BLOCK (0x${usbRamBlock.toString(16)}) for FLASH_WRITE_SIZE (USB-OTG)`); |
| 656 | + } |
| 657 | + } |
| 658 | + |
588 | 659 | /** |
589 | 660 | * Constructs a sequence of reset strategies based on the OS, |
590 | 661 | * used ESP chip, external settings, and environment variables. |
@@ -1272,6 +1343,8 @@ export class ESPLoader { |
1272 | 1343 | async runStub(): Promise<ROM> { |
1273 | 1344 | if (this.syncStubDetected) { |
1274 | 1345 | this.info("Stub is already running. No upload is necessary."); |
| 1346 | + this.IS_STUB = true; |
| 1347 | + await this.applyUsbFlashWriteSize(); |
1275 | 1348 | return this.chip; |
1276 | 1349 | } |
1277 | 1350 |
|
@@ -1311,6 +1384,7 @@ export class ESPLoader { |
1311 | 1384 |
|
1312 | 1385 | this.info("Stub running..."); |
1313 | 1386 | this.IS_STUB = true; |
| 1387 | + await this.applyUsbFlashWriteSize(); |
1314 | 1388 | return this.chip; |
1315 | 1389 | } |
1316 | 1390 |
|
|
0 commit comments