esp32tool 1.1.8 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/.nojekyll +0 -0
  2. package/README.md +100 -6
  3. package/apple-touch-icon.png +0 -0
  4. package/build-electron-cli.cjs +177 -0
  5. package/build-single-binary.cjs +295 -0
  6. package/css/light.css +11 -0
  7. package/css/style.css +225 -35
  8. package/dist/cli.d.ts +17 -0
  9. package/dist/cli.js +458 -0
  10. package/dist/esp_loader.d.ts +129 -21
  11. package/dist/esp_loader.js +1227 -222
  12. package/dist/index.d.ts +2 -1
  13. package/dist/index.js +37 -4
  14. package/dist/node-usb-adapter.d.ts +47 -0
  15. package/dist/node-usb-adapter.js +725 -0
  16. package/dist/stubs/index.d.ts +1 -2
  17. package/dist/stubs/index.js +4 -0
  18. package/dist/web/index.js +1 -1
  19. package/electron/cli-main.cjs +74 -0
  20. package/electron/main.cjs +338 -0
  21. package/electron/main.js +7 -2
  22. package/favicon.ico +0 -0
  23. package/fix-cli-imports.cjs +127 -0
  24. package/generate-icons.sh +89 -0
  25. package/icons/icon-128.png +0 -0
  26. package/icons/icon-144.png +0 -0
  27. package/icons/icon-152.png +0 -0
  28. package/icons/icon-192.png +0 -0
  29. package/icons/icon-384.png +0 -0
  30. package/icons/icon-512.png +0 -0
  31. package/icons/icon-72.png +0 -0
  32. package/icons/icon-96.png +0 -0
  33. package/index.html +94 -64
  34. package/install-android.html +411 -0
  35. package/js/modules/esptool.js +1 -1
  36. package/js/script.js +165 -160
  37. package/js/webusb-serial.js +1017 -0
  38. package/license.md +1 -1
  39. package/manifest.json +89 -0
  40. package/package.cli.json +29 -0
  41. package/package.json +31 -21
  42. package/screenshots/desktop.png +0 -0
  43. package/screenshots/mobile.png +0 -0
  44. package/src/cli.ts +618 -0
  45. package/src/esp_loader.ts +1438 -254
  46. package/src/index.ts +69 -3
  47. package/src/node-usb-adapter.ts +924 -0
  48. package/src/stubs/index.ts +4 -1
  49. package/sw.js +155 -0
package/dist/cli.js ADDED
@@ -0,0 +1,458 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * ESP32Tool CLI - Command Line Interface for ESP device flashing
4
+ *
5
+ * Provides esptool.py-like commands for flashing ESP devices via WebSerial/WebUSB
6
+ *
7
+ * Usage:
8
+ * esp32tool flash-id
9
+ * esp32tool read-flash <offset> <size> <filename>
10
+ * esp32tool write-flash <offset> <filename>
11
+ * esp32tool erase-flash
12
+ * esp32tool erase-region <offset> <size>
13
+ * esp32tool chip-id
14
+ * esp32tool read-mac
15
+ */
16
+ import { ESPLoader } from "./esp_loader";
17
+ import { createNodeUSBAdapter, listUSBPorts } from "./node-usb-adapter";
18
+ import * as fs from "fs";
19
+ // CLI Logger
20
+ const cliLogger = {
21
+ log: (msg) => console.log(msg),
22
+ error: (msg) => console.error(`ERROR: ${msg}`),
23
+ debug: (msg) => {
24
+ if (process.env.DEBUG) {
25
+ console.log(`DEBUG: ${msg}`);
26
+ }
27
+ },
28
+ };
29
+ function parseArgs() {
30
+ const args = process.argv.slice(2);
31
+ if (args.length === 0) {
32
+ showHelp();
33
+ process.exit(1);
34
+ }
35
+ const result = {
36
+ command: "",
37
+ args: [],
38
+ baudRate: 115200,
39
+ };
40
+ let i = 0;
41
+ while (i < args.length) {
42
+ const arg = args[i];
43
+ if (arg === "--port" || arg === "-p") {
44
+ if (i + 1 >= args.length) {
45
+ console.error("Error: --port requires a value");
46
+ process.exit(1);
47
+ }
48
+ result.port = args[++i];
49
+ }
50
+ else if (arg === "--baud" || arg === "-b") {
51
+ if (i + 1 >= args.length) {
52
+ console.error("Error: --baud requires a value");
53
+ process.exit(1);
54
+ }
55
+ const baud = parseInt(args[++i], 10);
56
+ if (isNaN(baud) || baud <= 0) {
57
+ console.error("Error: --baud must be a positive integer");
58
+ process.exit(1);
59
+ }
60
+ result.baudRate = baud;
61
+ }
62
+ else if (arg === "--help" || arg === "-h") {
63
+ showHelp();
64
+ process.exit(0);
65
+ }
66
+ else if (!result.command) {
67
+ result.command = arg;
68
+ }
69
+ else {
70
+ result.args.push(arg);
71
+ }
72
+ i++;
73
+ }
74
+ return result;
75
+ }
76
+ function parseHexValue(value, paramName) {
77
+ // Remove optional 0x prefix
78
+ const cleanValue = value.toLowerCase().startsWith("0x")
79
+ ? value.slice(2)
80
+ : value;
81
+ // Validate hex format
82
+ if (!/^[0-9a-f]+$/i.test(cleanValue)) {
83
+ throw new Error(`Invalid ${paramName}: '${value}' is not a valid hexadecimal value`);
84
+ }
85
+ const parsed = parseInt(cleanValue, 16);
86
+ if (isNaN(parsed)) {
87
+ throw new Error(`Invalid ${paramName}: '${value}' could not be parsed as hexadecimal`);
88
+ }
89
+ if (parsed < 0) {
90
+ throw new Error(`Invalid ${paramName}: '${value}' must be non-negative`);
91
+ }
92
+ return parsed;
93
+ }
94
+ function showHelp() {
95
+ console.log(`
96
+ ESP32Tool CLI - Flash ESP devices via WebSerial/WebUSB
97
+
98
+ Usage: esp32tool [options] <command> [args...]
99
+
100
+ Options:
101
+ --port, -p <port> Serial port path (e.g., /dev/ttyUSB0)
102
+ --baud, -b <rate> Baud rate (default: 115200)
103
+ --help, -h Show this help message
104
+
105
+ Commands:
106
+ list-ports List available serial ports
107
+ chip-id Read chip ID
108
+ flash-id Read SPI flash manufacturer and device ID
109
+ read-mac Read MAC address
110
+ read-flash <offset> <size> <filename>
111
+ Read flash memory to file
112
+ write-flash <offset> <filename>
113
+ Write file to flash memory
114
+ erase-flash Erase entire flash chip
115
+ erase-region <offset> <size>
116
+ Erase a region of flash
117
+ verify-flash <offset> <filename>
118
+ Verify flash contents against file
119
+
120
+ Examples:
121
+ esp32tool list-ports
122
+ esp32tool --port /dev/ttyUSB0 chip-id
123
+ esp32tool --port /dev/ttyUSB0 flash-id
124
+ esp32tool --port /dev/ttyUSB0 read-mac
125
+ esp32tool --port /dev/ttyUSB0 read-flash 0x0 0x400000 flash_dump.bin
126
+ esp32tool --port /dev/ttyUSB0 write-flash 0x1000 bootloader.bin
127
+ esp32tool --port /dev/ttyUSB0 erase-flash
128
+ esp32tool --port /dev/ttyUSB0 erase-region 0x9000 0x6000
129
+
130
+ Note: This CLI requires Node.js with SerialPort support.
131
+ For browser-based usage, use the web interface instead.
132
+ `);
133
+ }
134
+ // Connect to ESP device
135
+ async function connectToDevice(portPath, baudRate = 115200) {
136
+ // List available ports if none specified
137
+ if (!portPath) {
138
+ cliLogger.log("No port specified. Available USB devices:");
139
+ const usbPorts = await listUSBPorts();
140
+ if (usbPorts.length === 0) {
141
+ throw new Error("No USB devices found");
142
+ }
143
+ usbPorts.forEach((port, idx) => {
144
+ console.log(` [${idx}] ${port.path}`);
145
+ });
146
+ throw new Error("Please specify a device with --port <USB:vid:pid>");
147
+ }
148
+ cliLogger.log(`Connecting to ${portPath} at ${baudRate} baud...`);
149
+ // Parse port path - support USB:vid:pid format
150
+ let targetVid;
151
+ let targetPid;
152
+ if (portPath.toUpperCase().startsWith("USB:")) {
153
+ // Format: USB:vid:pid
154
+ const parts = portPath.split(":");
155
+ if (parts.length === 3) {
156
+ targetVid = parseInt(parts[1], 16);
157
+ targetPid = parseInt(parts[2], 16);
158
+ }
159
+ }
160
+ return await connectViaUSB(targetVid, targetPid, baudRate);
161
+ }
162
+ // Connect via USB (direct USB access)
163
+ async function connectViaUSB(targetVid, targetPid, baudRate) {
164
+ let webPort = null;
165
+ try {
166
+ const usb = await import("usb");
167
+ // Find USB device
168
+ const devices = usb.getDeviceList();
169
+ let device;
170
+ if (targetVid !== undefined && targetPid !== undefined) {
171
+ device = devices.find((d) => d.deviceDescriptor.idVendor === targetVid &&
172
+ d.deviceDescriptor.idProduct === targetPid);
173
+ if (!device) {
174
+ throw new Error(`USB device not found: VID=0x${targetVid.toString(16)}, PID=0x${targetPid.toString(16)}`);
175
+ }
176
+ }
177
+ else {
178
+ // Find first USB-Serial device
179
+ device = devices.find((d) => {
180
+ const vid = d.deviceDescriptor.idVendor;
181
+ return (vid === 0x303a || // Espressif
182
+ vid === 0x0403 || // FTDI
183
+ vid === 0x1a86 || // CH340/CH343
184
+ vid === 0x10c4 || // CP210x
185
+ vid === 0x067b); // PL2303
186
+ });
187
+ if (!device) {
188
+ throw new Error("No USB-Serial device found. Run 'list-ports' to see available devices.");
189
+ }
190
+ cliLogger.log(`Auto-detected USB device: VID=0x${device.deviceDescriptor.idVendor.toString(16)}, PID=0x${device.deviceDescriptor.idProduct.toString(16)}`);
191
+ }
192
+ // Create USB adapter
193
+ webPort = createNodeUSBAdapter(device, cliLogger);
194
+ // ALWAYS open at 115200 baud (ROM bootloader speed)
195
+ await webPort.open({ baudRate: 115200 });
196
+ // Create ESPLoader instance
197
+ const esploader = new ESPLoader(webPort, cliLogger);
198
+ // Initialize connection at ROM speed
199
+ await esploader.initialize();
200
+ cliLogger.log(`Connected to ${esploader.chipName || esploader.chipFamily}`);
201
+ // Load stub code for better performance and features
202
+ const stub = await esploader.runStub();
203
+ // Change to requested baudrate if different from ROM speed
204
+ if (baudRate !== 115200) {
205
+ try {
206
+ await stub.setBaudrate(baudRate);
207
+ cliLogger.log(`Baudrate changed to ${baudRate}`);
208
+ }
209
+ catch (err) {
210
+ cliLogger.log(`Warning: Could not change baudrate: ${err.message}`);
211
+ }
212
+ }
213
+ return stub;
214
+ }
215
+ catch (err) {
216
+ // Clean up port on failure
217
+ if (webPort) {
218
+ try {
219
+ await webPort.close();
220
+ }
221
+ catch (closeErr) {
222
+ // Ignore close errors
223
+ }
224
+ }
225
+ // Check for permission errors
226
+ if (err.message && err.message.includes("LIBUSB_ERROR_ACCESS")) {
227
+ throw new Error("USB access denied. On macOS/Linux, you may need to run with sudo:\n" +
228
+ "Or use the Electron GUI version which doesn't require special permissions.");
229
+ }
230
+ throw err;
231
+ }
232
+ }
233
+ // Command implementations
234
+ async function cmdChipId(esploader) {
235
+ cliLogger.log(`Chip Family: ${esploader.chipFamily}`);
236
+ cliLogger.log(`Chip Name: ${esploader.chipName || "Unknown"}`);
237
+ if (esploader.chipRevision !== null) {
238
+ cliLogger.log(`Chip Revision: ${esploader.chipRevision}`);
239
+ }
240
+ if (esploader.chipVariant) {
241
+ cliLogger.log(`Chip Variant: ${esploader.chipVariant}`);
242
+ }
243
+ }
244
+ async function cmdFlashId(esploader) {
245
+ // Detect flash size using the stub
246
+ const stub = await esploader.runStub();
247
+ // detectFlashSize() is already called by runStub()
248
+ cliLogger.log(`Flash Size: ${stub.flashSize || "Unknown"}`);
249
+ }
250
+ async function cmdReadMac(esploader) {
251
+ const mac = await esploader.getMacAddress();
252
+ cliLogger.log(`MAC Address: ${mac}`);
253
+ }
254
+ async function cmdReadFlash(esploader, offset, size, filename) {
255
+ cliLogger.log(`Reading ${size} bytes from offset 0x${offset.toString(16)}...`);
256
+ // esploader is already a stub loader from connectViaUSB with correct baudrate
257
+ let lastProgress = 0;
258
+ const data = await esploader.readFlash(offset, size, (packet, progress, totalSize) => {
259
+ const percent = Math.round((progress / totalSize) * 100);
260
+ // Only update display every 1% to avoid too many updates
261
+ if (percent > lastProgress) {
262
+ lastProgress = percent;
263
+ process.stdout.write(`\rProgress: ${percent}% (${progress}/${totalSize} bytes)`);
264
+ }
265
+ });
266
+ console.log(""); // New line after progress
267
+ fs.writeFileSync(filename, Buffer.from(data));
268
+ cliLogger.log(`Saved to ${filename}`);
269
+ }
270
+ async function cmdWriteFlash(esploader, offset, filename) {
271
+ if (!fs.existsSync(filename)) {
272
+ throw new Error(`File not found: ${filename}`);
273
+ }
274
+ const fileData = fs.readFileSync(filename);
275
+ const size = fileData.byteLength;
276
+ cliLogger.log(`Writing ${size} bytes to offset 0x${offset.toString(16)}...`);
277
+ // Use stub for writing
278
+ const stub = await esploader.runStub();
279
+ // Write flash using the stub's flash methods
280
+ // Create a proper ArrayBuffer from the Buffer to avoid byteOffset issues
281
+ // Node.js Buffer can share an underlying ArrayBuffer with non-zero byteOffset
282
+ const arrayBuffer = fileData.buffer.slice(fileData.byteOffset, fileData.byteOffset + fileData.byteLength);
283
+ await stub.flashData(arrayBuffer, (bytesWritten, totalBytes) => {
284
+ const percent = Math.round((bytesWritten / totalBytes) * 100);
285
+ process.stdout.write(`\rProgress: ${percent}% (${bytesWritten}/${totalBytes} bytes)`);
286
+ }, offset);
287
+ console.log(""); // New line after progress
288
+ cliLogger.log("Write complete!");
289
+ }
290
+ async function cmdEraseFlash(esploader) {
291
+ cliLogger.log("Erasing entire flash chip...");
292
+ // Use stub for erasing
293
+ const stub = await esploader.runStub();
294
+ // Erase flash
295
+ await stub.eraseFlash();
296
+ cliLogger.log("Erase complete!");
297
+ }
298
+ async function cmdEraseRegion(esploader, offset, size) {
299
+ cliLogger.log(`Erasing region: offset=0x${offset.toString(16)}, size=0x${size.toString(16)}...`);
300
+ // Use stub for erasing
301
+ const stub = await esploader.runStub();
302
+ // Erase region
303
+ await stub.eraseRegion(offset, size);
304
+ cliLogger.log("Erase complete!");
305
+ }
306
+ async function cmdVerifyFlash(esploader, offset, filename) {
307
+ if (!fs.existsSync(filename)) {
308
+ throw new Error(`File not found: ${filename}`);
309
+ }
310
+ const fileData = fs.readFileSync(filename);
311
+ const size = fileData.length;
312
+ cliLogger.log(`Verifying ${size} bytes at offset 0x${offset.toString(16)}...`);
313
+ // Use stub for reading
314
+ const stub = await esploader.runStub();
315
+ let lastProgress = 0;
316
+ const flashData = await stub.readFlash(offset, size, (packet, progress, totalSize) => {
317
+ const percent = Math.round((progress / totalSize) * 100);
318
+ // Only update display every 1% to avoid too many updates
319
+ if (percent > lastProgress) {
320
+ lastProgress = percent;
321
+ process.stdout.write(`\rReading: ${percent}% (${progress}/${totalSize} bytes)`);
322
+ }
323
+ });
324
+ console.log(""); // New line after progress
325
+ cliLogger.log("Comparing data...");
326
+ if (Buffer.compare(Buffer.from(flashData), fileData) === 0) {
327
+ cliLogger.log("Verification successful!");
328
+ }
329
+ else {
330
+ throw new Error("Verification failed! Flash contents do not match file.");
331
+ }
332
+ }
333
+ // Main CLI entry point
334
+ async function main() {
335
+ const cliArgs = parseArgs();
336
+ let esploader = null;
337
+ try {
338
+ // Validate command
339
+ if (!cliArgs.command) {
340
+ showHelp();
341
+ process.exit(1);
342
+ }
343
+ // Special command: list-ports (doesn't need device connection)
344
+ if (cliArgs.command === "list-ports") {
345
+ const usbPorts = await listUSBPorts();
346
+ if (usbPorts.length === 0) {
347
+ cliLogger.log("No USB devices found");
348
+ }
349
+ else {
350
+ cliLogger.log("Available USB devices:");
351
+ usbPorts.forEach((port) => {
352
+ console.log(` ${port.path}${port.manufacturer ? ` (${port.manufacturer})` : ""}${port.serialNumber ? ` [${port.serialNumber}]` : ""}`);
353
+ });
354
+ }
355
+ // Clean exit without process.exit() to avoid native module cleanup issues
356
+ return;
357
+ }
358
+ // Connect to device
359
+ esploader = await connectToDevice(cliArgs.port, cliArgs.baudRate);
360
+ // Execute command
361
+ switch (cliArgs.command) {
362
+ case "chip-id":
363
+ await cmdChipId(esploader);
364
+ break;
365
+ case "flash-id":
366
+ await cmdFlashId(esploader);
367
+ break;
368
+ case "read-mac":
369
+ await cmdReadMac(esploader);
370
+ break;
371
+ case "read-flash": {
372
+ if (cliArgs.args.length < 3) {
373
+ throw new Error("read-flash requires: <offset> <size> <filename>");
374
+ }
375
+ const offset = parseHexValue(cliArgs.args[0], "offset");
376
+ const size = parseHexValue(cliArgs.args[1], "size");
377
+ const filename = cliArgs.args[2];
378
+ await cmdReadFlash(esploader, offset, size, filename);
379
+ break;
380
+ }
381
+ case "write-flash": {
382
+ if (cliArgs.args.length < 2) {
383
+ throw new Error("write-flash requires: <offset> <filename>");
384
+ }
385
+ const offset = parseHexValue(cliArgs.args[0], "offset");
386
+ const filename = cliArgs.args[1];
387
+ await cmdWriteFlash(esploader, offset, filename);
388
+ break;
389
+ }
390
+ case "erase-flash":
391
+ await cmdEraseFlash(esploader);
392
+ break;
393
+ case "erase-region": {
394
+ if (cliArgs.args.length < 2) {
395
+ throw new Error("erase-region requires: <offset> <size>");
396
+ }
397
+ const offset = parseHexValue(cliArgs.args[0], "offset");
398
+ const size = parseHexValue(cliArgs.args[1], "size");
399
+ await cmdEraseRegion(esploader, offset, size);
400
+ break;
401
+ }
402
+ case "verify-flash": {
403
+ if (cliArgs.args.length < 2) {
404
+ throw new Error("verify-flash requires: <offset> <filename>");
405
+ }
406
+ const offset = parseHexValue(cliArgs.args[0], "offset");
407
+ const filename = cliArgs.args[1];
408
+ await cmdVerifyFlash(esploader, offset, filename);
409
+ break;
410
+ }
411
+ default:
412
+ throw new Error(`Unknown command: ${cliArgs.command}`);
413
+ }
414
+ // Disconnect
415
+ await esploader.disconnect();
416
+ // Force exit after a short delay to ensure clean shutdown
417
+ // This is necessary for node-usb which may have pending callbacks
418
+ setTimeout(() => {
419
+ process.exit(0);
420
+ }, 100);
421
+ // Clean exit - let Electron handle the exit
422
+ return;
423
+ }
424
+ catch (error) {
425
+ // Clean up device connection on failure
426
+ if (esploader) {
427
+ try {
428
+ await esploader.disconnect();
429
+ }
430
+ catch (disconnectErr) {
431
+ // Ignore disconnect errors during error handling
432
+ }
433
+ }
434
+ cliLogger.error(error.message);
435
+ if (process.env.DEBUG) {
436
+ console.error(error.stack);
437
+ }
438
+ process.exit(1);
439
+ }
440
+ }
441
+ // Run CLI - only execute when this file is run directly (not when imported)
442
+ // Check if we're being run directly by Node.js (not imported by Electron)
443
+ const isDirectRun = process.argv[1] &&
444
+ (process.argv[1].endsWith("/cli.js") ||
445
+ process.argv[1].endsWith("\\cli.js") ||
446
+ process.argv[1].endsWith("/cli-fixed.js") ||
447
+ process.argv[1].endsWith("\\cli-fixed.js") ||
448
+ process.argv[1].endsWith("/esp32tool") ||
449
+ process.argv[1].endsWith("\\esp32tool") ||
450
+ process.argv[1].endsWith("/esp32tool.exe") ||
451
+ process.argv[1].endsWith("\\esp32tool.exe"));
452
+ if (isDirectRun) {
453
+ main().catch((err) => {
454
+ console.error(err);
455
+ process.exit(1);
456
+ });
457
+ }
458
+ export { main as runCLI };
@@ -3,10 +3,10 @@ export declare class ESPLoader extends EventTarget {
3
3
  port: SerialPort;
4
4
  logger: Logger;
5
5
  private _parent?;
6
- chipFamily: ChipFamily;
7
- chipName: string | null;
8
- chipRevision: number | null;
9
- chipVariant: string | null;
6
+ __chipFamily?: ChipFamily;
7
+ __chipName: string | null;
8
+ __chipRevision: number | null;
9
+ __chipVariant: string | null;
10
10
  _efuses: any[];
11
11
  _flashsize: number;
12
12
  debug: boolean;
@@ -14,6 +14,7 @@ export declare class ESPLoader extends EventTarget {
14
14
  connected: boolean;
15
15
  flashSize: string | null;
16
16
  __inputBuffer?: number[];
17
+ __inputBufferReadIndex?: number;
17
18
  __totalBytesRead?: number;
18
19
  private _currentBaudRate;
19
20
  private _maxUSBSerialBaudrate?;
@@ -21,13 +22,47 @@ export declare class ESPLoader extends EventTarget {
21
22
  private _isESP32S2NativeUSB;
22
23
  private _initializationSucceeded;
23
24
  private __commandLock;
24
- private _isReconfiguring;
25
+ private __isReconfiguring;
26
+ private __abandonCurrentOperation;
27
+ private __adaptiveBlockMultiplier;
28
+ private __adaptiveMaxInFlightMultiplier;
29
+ private __consecutiveSuccessfulChunks;
30
+ private __lastAdaptiveAdjustment;
31
+ private __isCDCDevice;
25
32
  constructor(port: SerialPort, logger: Logger, _parent?: ESPLoader | undefined);
33
+ get chipFamily(): ChipFamily;
34
+ set chipFamily(value: ChipFamily);
35
+ get chipName(): string | null;
36
+ set chipName(value: string | null);
37
+ get chipRevision(): number | null;
38
+ set chipRevision(value: number | null);
39
+ get chipVariant(): string | null;
40
+ set chipVariant(value: string | null);
26
41
  private get _inputBuffer();
42
+ private get _inputBufferReadIndex();
43
+ private set _inputBufferReadIndex(value);
44
+ private get _inputBufferAvailable();
45
+ private _readByte;
46
+ private _clearInputBuffer;
47
+ private _compactInputBuffer;
27
48
  private get _totalBytesRead();
28
49
  private set _totalBytesRead(value);
29
50
  private get _commandLock();
30
51
  private set _commandLock(value);
52
+ private get _isReconfiguring();
53
+ private set _isReconfiguring(value);
54
+ private get _abandonCurrentOperation();
55
+ private set _abandonCurrentOperation(value);
56
+ private get _adaptiveBlockMultiplier();
57
+ private set _adaptiveBlockMultiplier(value);
58
+ private get _adaptiveMaxInFlightMultiplier();
59
+ private set _adaptiveMaxInFlightMultiplier(value);
60
+ private get _consecutiveSuccessfulChunks();
61
+ private set _consecutiveSuccessfulChunks(value);
62
+ private get _lastAdaptiveAdjustment();
63
+ private set _lastAdaptiveAdjustment(value);
64
+ private get _isCDCDevice();
65
+ private set _isCDCDevice(value);
31
66
  private detectUSBSerialChip;
32
67
  initialize(): Promise<void>;
33
68
  /**
@@ -48,6 +83,10 @@ export declare class ESPLoader extends EventTarget {
48
83
  chipId: number;
49
84
  apiVersion: number;
50
85
  }>;
86
+ /**
87
+ * Get MAC address from efuses
88
+ */
89
+ getMacAddress(): Promise<string>;
51
90
  /**
52
91
  * @name readLoop
53
92
  * Reads data from the input stream and places it in the inputBuffer
@@ -55,8 +94,78 @@ export declare class ESPLoader extends EventTarget {
55
94
  readLoop(): Promise<void>;
56
95
  sleep(ms?: number): Promise<unknown>;
57
96
  state_DTR: boolean;
97
+ state_RTS: boolean;
58
98
  setRTS(state: boolean): Promise<void>;
59
99
  setDTR(state: boolean): Promise<void>;
100
+ /**
101
+ * @name hardResetUSBJTAGSerial
102
+ * USB-JTAG/Serial reset for Web Serial (Desktop)
103
+ */
104
+ hardResetUSBJTAGSerial(): Promise<void>;
105
+ /**
106
+ * @name hardResetClassic
107
+ * Classic reset for Web Serial (Desktop)
108
+ */
109
+ hardResetClassic(): Promise<void>;
110
+ setRTSWebUSB(state: boolean): Promise<void>;
111
+ setDTRWebUSB(state: boolean): Promise<void>;
112
+ setDTRandRTSWebUSB(dtr: boolean, rts: boolean): Promise<void>;
113
+ /**
114
+ * @name hardResetUSBJTAGSerialWebUSB
115
+ * USB-JTAG/Serial reset for WebUSB (Android)
116
+ */
117
+ hardResetUSBJTAGSerialWebUSB(): Promise<void>;
118
+ /**
119
+ * @name hardResetUSBJTAGSerialInvertedDTRWebUSB
120
+ * USB-JTAG/Serial reset with inverted DTR for WebUSB (Android)
121
+ */
122
+ hardResetUSBJTAGSerialInvertedDTRWebUSB(): Promise<void>;
123
+ /**
124
+ * @name hardResetClassicWebUSB
125
+ * Classic reset for WebUSB (Android)
126
+ */
127
+ hardResetClassicWebUSB(): Promise<void>;
128
+ /**
129
+ * @name hardResetUnixTightWebUSB
130
+ * Unix Tight reset for WebUSB (Android) - sets DTR and RTS simultaneously
131
+ */
132
+ hardResetUnixTightWebUSB(): Promise<void>;
133
+ /**
134
+ * @name hardResetClassicLongDelayWebUSB
135
+ * Classic reset with longer delays for WebUSB (Android)
136
+ * Specifically for CP2102/CH340 which may need more time
137
+ */
138
+ hardResetClassicLongDelayWebUSB(): Promise<void>;
139
+ /**
140
+ * @name hardResetClassicShortDelayWebUSB
141
+ * Classic reset with shorter delays for WebUSB (Android)
142
+ */
143
+ hardResetClassicShortDelayWebUSB(): Promise<void>;
144
+ /**
145
+ * @name hardResetInvertedWebUSB
146
+ * Inverted reset sequence for WebUSB (Android) - both signals inverted
147
+ */
148
+ hardResetInvertedWebUSB(): Promise<void>;
149
+ /**
150
+ * @name hardResetInvertedDTRWebUSB
151
+ * Only DTR inverted for WebUSB (Android)
152
+ */
153
+ hardResetInvertedDTRWebUSB(): Promise<void>;
154
+ /**
155
+ * @name hardResetInvertedRTSWebUSB
156
+ * Only RTS inverted for WebUSB (Android)
157
+ */
158
+ hardResetInvertedRTSWebUSB(): Promise<void>;
159
+ /**
160
+ * Check if we're using WebUSB (Android) or Web Serial (Desktop)
161
+ */
162
+ private isWebUSB;
163
+ /**
164
+ * @name connectWithResetStrategies
165
+ * Try different reset strategies to enter bootloader mode
166
+ * Similar to esptool.py's connect() method with multiple reset strategies
167
+ */
168
+ connectWithResetStrategies(): Promise<void>;
60
169
  hardReset(bootloader?: boolean): Promise<void>;
61
170
  /**
62
171
  * @name macAddr
@@ -84,6 +193,10 @@ export declare class ESPLoader extends EventTarget {
84
193
  * @name readPacket
85
194
  * Generator to read SLIP packets from a serial port.
86
195
  * Yields one full SLIP packet at a time, raises exception on timeout or invalid data.
196
+ *
197
+ * Two implementations:
198
+ * - Burst: CDC devices (Native USB) and CH343 - very fast processing
199
+ * - Byte-by-byte: CH340, CP2102, and other USB-Serial adapters - stable fast processing
87
200
  */
88
201
  readPacket(timeout: number): Promise<number[]>;
89
202
  /**
@@ -101,21 +214,11 @@ export declare class ESPLoader extends EventTarget {
101
214
  setBaudrate(baud: number): Promise<void>;
102
215
  reconfigurePort(baud: number): Promise<void>;
103
216
  /**
104
- * @name connectWithResetStrategies
105
- * Try different reset strategies to enter bootloader mode
106
- * Similar to esptool.py's connect() method with multiple reset strategies
107
- */
108
- connectWithResetStrategies(): Promise<void>;
109
- /**
110
- * @name hardResetUSBJTAGSerial
111
- * USB-JTAG/Serial reset sequence for ESP32-C3, ESP32-S3, ESP32-C6, etc.
217
+ * @name syncWithTimeout
218
+ * Sync with timeout that can be abandoned (for reset strategy loop)
219
+ * This is internally time-bounded and checks the abandon flag
112
220
  */
113
- hardResetUSBJTAGSerial(): Promise<void>;
114
- /**
115
- * @name hardResetClassic
116
- * Classic reset sequence for USB-to-Serial bridge chips (CH340, CP2102, etc.)
117
- */
118
- hardResetClassic(): Promise<void>;
221
+ syncWithTimeout(timeoutMs: number): Promise<boolean>;
119
222
  /**
120
223
  * @name sync
121
224
  * Put into ROM bootload mode & attempt to synchronize with the
@@ -243,9 +346,14 @@ declare class EspStubLoader extends ESPLoader {
243
346
  */
244
347
  memBegin(size: number, _blocks: number, _blocksize: number, offset: number): Promise<[number, number[]]>;
245
348
  /**
246
- * @name getEraseSize
247
- * depending on flash chip model the erase may take this long (maybe longer!)
349
+ * @name eraseFlash
350
+ * Erase entire flash chip
248
351
  */
249
352
  eraseFlash(): Promise<void>;
353
+ /**
354
+ * @name eraseRegion
355
+ * Erase a specific region of flash
356
+ */
357
+ eraseRegion(offset: number, size: number): Promise<void>;
250
358
  }
251
359
  export {};