webserial-flasher 1.0.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.
- package/LICENSE +21 -0
- package/README.md +97 -0
- package/dist/autoDetect.d.ts +24 -0
- package/dist/autoDetect.d.ts.map +1 -0
- package/dist/autoDetect.js +66 -0
- package/dist/autoDetect.js.map +1 -0
- package/dist/boards/database.d.ts +17 -0
- package/dist/boards/database.d.ts.map +1 -0
- package/dist/boards/database.js +957 -0
- package/dist/boards/database.js.map +1 -0
- package/dist/core/constants.d.ts +44 -0
- package/dist/core/constants.d.ts.map +1 -0
- package/dist/core/constants.js +56 -0
- package/dist/core/constants.js.map +1 -0
- package/dist/core/errors.d.ts +45 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +92 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/types.d.ts +138 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +3 -0
- package/dist/core/types.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/protocol/avr109/programmer.d.ts +78 -0
- package/dist/protocol/avr109/programmer.d.ts.map +1 -0
- package/dist/protocol/avr109/programmer.js +324 -0
- package/dist/protocol/avr109/programmer.js.map +1 -0
- package/dist/protocol/hexParser.d.ts +12 -0
- package/dist/protocol/hexParser.d.ts.map +1 -0
- package/dist/protocol/hexParser.js +133 -0
- package/dist/protocol/hexParser.js.map +1 -0
- package/dist/protocol/picoboot/constants.d.ts +65 -0
- package/dist/protocol/picoboot/constants.d.ts.map +1 -0
- package/dist/protocol/picoboot/constants.js +80 -0
- package/dist/protocol/picoboot/constants.js.map +1 -0
- package/dist/protocol/picoboot/programmer.d.ts +73 -0
- package/dist/protocol/picoboot/programmer.d.ts.map +1 -0
- package/dist/protocol/picoboot/programmer.js +278 -0
- package/dist/protocol/picoboot/programmer.js.map +1 -0
- package/dist/protocol/picoboot/uf2.d.ts +51 -0
- package/dist/protocol/picoboot/uf2.d.ts.map +1 -0
- package/dist/protocol/picoboot/uf2.js +119 -0
- package/dist/protocol/picoboot/uf2.js.map +1 -0
- package/dist/protocol/receiveData.d.ts +3 -0
- package/dist/protocol/receiveData.d.ts.map +1 -0
- package/dist/protocol/receiveData.js +72 -0
- package/dist/protocol/receiveData.js.map +1 -0
- package/dist/protocol/sendCommand.d.ts +14 -0
- package/dist/protocol/sendCommand.d.ts.map +1 -0
- package/dist/protocol/sendCommand.js +48 -0
- package/dist/protocol/sendCommand.js.map +1 -0
- package/dist/protocol/stk500v2/constants.d.ts +57 -0
- package/dist/protocol/stk500v2/constants.d.ts.map +1 -0
- package/dist/protocol/stk500v2/constants.js +62 -0
- package/dist/protocol/stk500v2/constants.js.map +1 -0
- package/dist/protocol/stk500v2/frame.d.ts +14 -0
- package/dist/protocol/stk500v2/frame.d.ts.map +1 -0
- package/dist/protocol/stk500v2/frame.js +116 -0
- package/dist/protocol/stk500v2/frame.js.map +1 -0
- package/dist/protocol/stk500v2/programmer.d.ts +92 -0
- package/dist/protocol/stk500v2/programmer.d.ts.map +1 -0
- package/dist/protocol/stk500v2/programmer.js +482 -0
- package/dist/protocol/stk500v2/programmer.js.map +1 -0
- package/dist/protocol/updi/constants.d.ts +107 -0
- package/dist/protocol/updi/constants.d.ts.map +1 -0
- package/dist/protocol/updi/constants.js +130 -0
- package/dist/protocol/updi/constants.js.map +1 -0
- package/dist/protocol/updi/link.d.ts +82 -0
- package/dist/protocol/updi/link.d.ts.map +1 -0
- package/dist/protocol/updi/link.js +241 -0
- package/dist/protocol/updi/link.js.map +1 -0
- package/dist/protocol/updi/programmer.d.ts +89 -0
- package/dist/protocol/updi/programmer.d.ts.map +1 -0
- package/dist/protocol/updi/programmer.js +359 -0
- package/dist/protocol/updi/programmer.js.map +1 -0
- package/dist/stk500.d.ts +101 -0
- package/dist/stk500.d.ts.map +1 -0
- package/dist/stk500.js +426 -0
- package/dist/stk500.js.map +1 -0
- package/dist/transport/IPicobootTransport.d.ts +25 -0
- package/dist/transport/IPicobootTransport.d.ts.map +1 -0
- package/dist/transport/IPicobootTransport.js +10 -0
- package/dist/transport/IPicobootTransport.js.map +1 -0
- package/dist/transport/ITransport.d.ts +33 -0
- package/dist/transport/ITransport.d.ts.map +1 -0
- package/dist/transport/ITransport.js +4 -0
- package/dist/transport/ITransport.js.map +1 -0
- package/dist/transport/NodeSerialTransport.d.ts +35 -0
- package/dist/transport/NodeSerialTransport.d.ts.map +1 -0
- package/dist/transport/NodeSerialTransport.js +102 -0
- package/dist/transport/NodeSerialTransport.js.map +1 -0
- package/dist/transport/NodeUSBTransport.d.ts +24 -0
- package/dist/transport/NodeUSBTransport.d.ts.map +1 -0
- package/dist/transport/NodeUSBTransport.js +146 -0
- package/dist/transport/NodeUSBTransport.js.map +1 -0
- package/dist/transport/WebSerialTransport.d.ts +63 -0
- package/dist/transport/WebSerialTransport.d.ts.map +1 -0
- package/dist/transport/WebSerialTransport.js +159 -0
- package/dist/transport/WebSerialTransport.js.map +1 -0
- package/package.json +79 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"receiveData.d.ts","sourceRoot":"","sources":["../../src/protocol/receiveData.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAMhE,MAAM,CAAC,OAAO,UAAU,WAAW,CACjC,SAAS,EAAE,aAAa,EACxB,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,UAAU,CAAC,CA+DrB"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// Receive a fixed-length response from the device.
|
|
2
|
+
//
|
|
3
|
+
// Fixes vs original:
|
|
4
|
+
// 1. settled flag prevents double-resolve after timeout
|
|
5
|
+
// 2. Timeout fires correctly even if INSYNC byte never arrives
|
|
6
|
+
// 3. Pre-allocated buffer avoids per-chunk Uint8Array concatenation
|
|
7
|
+
// 4. Cleanup always removes the data listener (no memory leak)
|
|
8
|
+
import Constants from '../core/constants.js';
|
|
9
|
+
import { STK500TimeoutError } from '../core/errors.js';
|
|
10
|
+
const INSYNC_BYTE = Constants.Resp_STK_INSYNC; // 0x14
|
|
11
|
+
export default function receiveData(transport, timeoutMs, responseLength) {
|
|
12
|
+
return new Promise((resolve, reject) => {
|
|
13
|
+
// Pre-allocate to avoid repeated array construction on each chunk
|
|
14
|
+
const buffer = new Uint8Array(responseLength);
|
|
15
|
+
let offset = 0;
|
|
16
|
+
let started = false;
|
|
17
|
+
let settled = false;
|
|
18
|
+
let timeoutId;
|
|
19
|
+
const cleanup = () => {
|
|
20
|
+
if (timeoutId !== undefined)
|
|
21
|
+
clearTimeout(timeoutId);
|
|
22
|
+
transport.off('data', handleChunk);
|
|
23
|
+
};
|
|
24
|
+
const finish = (err, data) => {
|
|
25
|
+
if (settled)
|
|
26
|
+
return; // Guard against double-settle
|
|
27
|
+
settled = true;
|
|
28
|
+
cleanup();
|
|
29
|
+
if (err)
|
|
30
|
+
reject(err);
|
|
31
|
+
else
|
|
32
|
+
resolve(data);
|
|
33
|
+
};
|
|
34
|
+
const handleChunk = (chunk) => {
|
|
35
|
+
if (settled)
|
|
36
|
+
return;
|
|
37
|
+
let chunkStart = 0;
|
|
38
|
+
// Scan for the INSYNC sentinel byte before accumulating
|
|
39
|
+
if (!started) {
|
|
40
|
+
for (let i = 0; i < chunk.length; i++) {
|
|
41
|
+
if (chunk[i] === INSYNC_BYTE) {
|
|
42
|
+
chunkStart = i;
|
|
43
|
+
started = true;
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (!started)
|
|
48
|
+
return; // INSYNC not yet seen — keep waiting
|
|
49
|
+
}
|
|
50
|
+
const slice = chunk.subarray(chunkStart);
|
|
51
|
+
const remaining = responseLength - offset;
|
|
52
|
+
const toCopy = Math.min(slice.length, remaining);
|
|
53
|
+
buffer.set(slice.subarray(0, toCopy), offset);
|
|
54
|
+
offset += toCopy;
|
|
55
|
+
if (offset === responseLength) {
|
|
56
|
+
finish(undefined, buffer);
|
|
57
|
+
}
|
|
58
|
+
else if (offset > responseLength) {
|
|
59
|
+
// Should never happen with toCopy clamping, but guard anyway
|
|
60
|
+
finish(new Error(`Buffer overflow: received ${offset} > expected ${responseLength}`));
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
// Install timeout — fires even if INSYNC never arrives
|
|
64
|
+
if (timeoutMs > 0) {
|
|
65
|
+
timeoutId = setTimeout(() => {
|
|
66
|
+
finish(new STK500TimeoutError(timeoutMs, 'waiting for device response'));
|
|
67
|
+
}, timeoutMs);
|
|
68
|
+
}
|
|
69
|
+
transport.on('data', handleChunk);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=receiveData.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"receiveData.js","sourceRoot":"","sources":["../../src/protocol/receiveData.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ISTKTransport } from '../transport/ITransport.js';
|
|
2
|
+
interface SendCommandOptions {
|
|
3
|
+
/** Command bytes. Arrays automatically get Sync_CRC_EOP appended. */
|
|
4
|
+
cmd: Uint8Array | readonly number[];
|
|
5
|
+
/** Response timeout in ms. 0 = no timeout. */
|
|
6
|
+
timeout?: number;
|
|
7
|
+
/** Expected exact response bytes (length + content must match) */
|
|
8
|
+
responseData?: Uint8Array;
|
|
9
|
+
/** Expected response length when content doesn't need validation */
|
|
10
|
+
responseLength?: number;
|
|
11
|
+
}
|
|
12
|
+
export default function sendCommand(transport: ISTKTransport, opt: SendCommandOptions): Promise<Uint8Array>;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=sendCommand.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sendCommand.d.ts","sourceRoot":"","sources":["../../src/protocol/sendCommand.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAKhE,UAAU,kBAAkB;IAC1B,qEAAqE;IACrE,GAAG,EAAE,UAAU,GAAG,SAAS,MAAM,EAAE,CAAC;IACpC,8CAA8C;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kEAAkE;IAClE,YAAY,CAAC,EAAE,UAAU,CAAC;IAC1B,oEAAoE;IACpE,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,wBAA8B,WAAW,CACvC,SAAS,EAAE,aAAa,EACxB,GAAG,EAAE,kBAAkB,GACtB,OAAO,CAAC,UAAU,CAAC,CAgDrB"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// Send a command and wait for the response.
|
|
2
|
+
//
|
|
3
|
+
// Fixes vs original:
|
|
4
|
+
// 1. Length check before Array.every() — prevents silent false-pass when
|
|
5
|
+
// data.length > responseData.length (Array.every stops at caller length)
|
|
6
|
+
// 2. findIndex reports exact mismatch position in error messages
|
|
7
|
+
// 3. transport.write() is now async (Promise-based)
|
|
8
|
+
import Constants from '../core/constants.js';
|
|
9
|
+
import { STK500ProtocolError } from '../core/errors.js';
|
|
10
|
+
import receiveData from './receiveData.js';
|
|
11
|
+
export default async function sendCommand(transport, opt) {
|
|
12
|
+
const timeout = opt.timeout ?? 0;
|
|
13
|
+
// Determine how many bytes to collect
|
|
14
|
+
let expectedLength = 0;
|
|
15
|
+
if (opt.responseData && opt.responseData.length > 0) {
|
|
16
|
+
expectedLength = opt.responseData.length;
|
|
17
|
+
}
|
|
18
|
+
if (opt.responseLength) {
|
|
19
|
+
expectedLength = opt.responseLength; // responseLength wins over responseData.length
|
|
20
|
+
}
|
|
21
|
+
// Build the raw command — arrays get CRC_EOP appended, Uint8Arrays are sent as-is
|
|
22
|
+
let cmd;
|
|
23
|
+
if (Array.isArray(opt.cmd)) {
|
|
24
|
+
cmd = new Uint8Array([...opt.cmd, Constants.Sync_CRC_EOP]);
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
cmd = opt.cmd;
|
|
28
|
+
}
|
|
29
|
+
// Transmit
|
|
30
|
+
await transport.write(cmd);
|
|
31
|
+
// Collect response
|
|
32
|
+
const data = await receiveData(transport, timeout, expectedLength);
|
|
33
|
+
// Validate response content when caller provided expected bytes
|
|
34
|
+
if (opt.responseData && opt.responseData.length > 0) {
|
|
35
|
+
const expected = opt.responseData;
|
|
36
|
+
if (data.length !== expected.length) {
|
|
37
|
+
throw new STK500ProtocolError(`Response length mismatch: got ${data.length} bytes, expected ${expected.length}`);
|
|
38
|
+
}
|
|
39
|
+
const mismatchAt = data.findIndex((v, i) => v !== expected[i]);
|
|
40
|
+
if (mismatchAt !== -1) {
|
|
41
|
+
const hex = (b) => Array.from(b).map((x) => x.toString(16).padStart(2, '0')).join(' ');
|
|
42
|
+
throw new STK500ProtocolError(`Response mismatch at byte ${mismatchAt}: ` +
|
|
43
|
+
`expected [${hex(expected)}], got [${hex(data)}]`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return data;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=sendCommand.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sendCommand.js","sourceRoot":"","sources":["../../src/protocol/sendCommand.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,EAAE;AACF,qBAAqB;AACrB,2EAA2E;AAC3E,8EAA8E;AAC9E,mEAAmE;AACnE,sDAAsD;AAGtD,OAAO,SAAS,MAAM,sBAAsB,CAAC;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,WAAW,MAAM,kBAAkB,CAAC;AAa3C,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,WAAW,CACvC,SAAwB,EACxB,GAAuB;IAEvB,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC;IAEjC,sCAAsC;IACtC,IAAI,cAAc,GAAG,CAAC,CAAC;IACvB,IAAI,GAAG,CAAC,YAAY,IAAI,GAAG,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpD,cAAc,GAAG,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC;IAC3C,CAAC;IACD,IAAI,GAAG,CAAC,cAAc,EAAE,CAAC;QACvB,cAAc,GAAG,GAAG,CAAC,cAAc,CAAC,CAAC,+CAA+C;IACtF,CAAC;IAED,kFAAkF;IAClF,IAAI,GAAe,CAAC;IACpB,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3B,GAAG,GAAG,IAAI,UAAU,CAAC,CAAC,GAAI,GAAG,CAAC,GAAgB,EAAE,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC;IAC3E,CAAC;SAAM,CAAC;QACN,GAAG,GAAG,GAAG,CAAC,GAAiB,CAAC;IAC9B,CAAC;IAED,WAAW;IACX,MAAM,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAE3B,mBAAmB;IACnB,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,SAAS,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC;IAEnE,gEAAgE;IAChE,IAAI,GAAG,CAAC,YAAY,IAAI,GAAG,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpD,MAAM,QAAQ,GAAG,GAAG,CAAC,YAAY,CAAC;QAElC,IAAI,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,EAAE,CAAC;YACpC,MAAM,IAAI,mBAAmB,CAC3B,iCAAiC,IAAI,CAAC,MAAM,oBAAoB,QAAQ,CAAC,MAAM,EAAE,CAClF,CAAC;QACJ,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/D,IAAI,UAAU,KAAK,CAAC,CAAC,EAAE,CAAC;YACtB,MAAM,GAAG,GAAG,CAAC,CAAa,EAAU,EAAE,CACpC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACtE,MAAM,IAAI,mBAAmB,CAC3B,6BAA6B,UAAU,IAAI;gBACzC,aAAa,GAAG,CAAC,QAAQ,CAAC,WAAW,GAAG,CAAC,IAAI,CAAC,GAAG,CACpD,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/** Frame delimiter — every message starts with this byte */
|
|
2
|
+
export declare const MSG_START = 27;
|
|
3
|
+
/** Token — separates the 4-byte header from the message body */
|
|
4
|
+
export declare const MSG_TOKEN = 14;
|
|
5
|
+
/** Command bytes sent by the master (programmer) */
|
|
6
|
+
export declare const Cmd: {
|
|
7
|
+
readonly SIGN_ON: 1;
|
|
8
|
+
readonly SET_PARAMETER: 2;
|
|
9
|
+
readonly GET_PARAMETER: 3;
|
|
10
|
+
readonly SET_DEVICE_DESCRIPTOR: 4;
|
|
11
|
+
readonly OSCCAL: 5;
|
|
12
|
+
readonly LOAD_ADDRESS: 6;
|
|
13
|
+
readonly FIRMWARE_UPGRADE: 7;
|
|
14
|
+
readonly ENTER_PROGMODE_ISP: 16;
|
|
15
|
+
readonly LEAVE_PROGMODE_ISP: 17;
|
|
16
|
+
readonly CHIP_ERASE_ISP: 18;
|
|
17
|
+
readonly PROGRAM_FLASH_ISP: 19;
|
|
18
|
+
readonly READ_FLASH_ISP: 20;
|
|
19
|
+
readonly PROGRAM_EEPROM_ISP: 21;
|
|
20
|
+
readonly READ_EEPROM_ISP: 22;
|
|
21
|
+
readonly PROGRAM_FUSE_ISP: 23;
|
|
22
|
+
readonly READ_FUSE_ISP: 24;
|
|
23
|
+
readonly PROGRAM_LOCK_ISP: 25;
|
|
24
|
+
readonly READ_LOCK_ISP: 26;
|
|
25
|
+
readonly READ_SIGNATURE_ISP: 27;
|
|
26
|
+
readonly READ_OSCCAL_ISP: 28;
|
|
27
|
+
readonly SPI_MULTI: 29;
|
|
28
|
+
};
|
|
29
|
+
/** Status codes returned in response bodies */
|
|
30
|
+
export declare const Status: {
|
|
31
|
+
readonly CMD_OK: 0;
|
|
32
|
+
readonly CMD_TOUT: 128;
|
|
33
|
+
readonly RDY_BSY_TOUT: 129;
|
|
34
|
+
readonly SET_PARAM_MISSING: 130;
|
|
35
|
+
readonly CMD_FAILED: 192;
|
|
36
|
+
readonly CMD_UNKNOWN: 201;
|
|
37
|
+
readonly ISP_READY: 0;
|
|
38
|
+
};
|
|
39
|
+
/** Programmer parameter IDs (used with SET/GET_PARAMETER) */
|
|
40
|
+
export declare const Param: {
|
|
41
|
+
readonly BUILD_NUMBER_LOW: 128;
|
|
42
|
+
readonly BUILD_NUMBER_HIGH: 129;
|
|
43
|
+
readonly HW_VER: 144;
|
|
44
|
+
readonly SW_MAJOR: 145;
|
|
45
|
+
readonly SW_MINOR: 146;
|
|
46
|
+
readonly VTARGET: 148;
|
|
47
|
+
readonly VADJUST: 149;
|
|
48
|
+
readonly OSC_PSCALE: 150;
|
|
49
|
+
readonly OSC_CMATCH: 151;
|
|
50
|
+
readonly SCK_DURATION: 152;
|
|
51
|
+
readonly TOPCARD_DETECT: 154;
|
|
52
|
+
readonly STATUS: 156;
|
|
53
|
+
readonly DATA: 157;
|
|
54
|
+
readonly RESET_POLARITY: 158;
|
|
55
|
+
readonly CONTROLLER_INIT: 159;
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/protocol/stk500v2/constants.ts"],"names":[],"mappings":"AAIA,4DAA4D;AAC5D,eAAO,MAAM,SAAS,KAAO,CAAC;AAC9B,gEAAgE;AAChE,eAAO,MAAM,SAAS,KAAO,CAAC;AAE9B,oDAAoD;AACpD,eAAO,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;CAyBN,CAAC;AAEX,+CAA+C;AAC/C,eAAO,MAAM,MAAM;;;;;;;;CAQT,CAAC;AAEX,6DAA6D;AAC7D,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;CAgBR,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// STK500v2 protocol constants.
|
|
2
|
+
// Used by the wiring/ISP bootloader (Arduino Mega 2560, STK600, etc.)
|
|
3
|
+
// Reference: Atmel Application Note AVR068 — STK500 Communication Protocol
|
|
4
|
+
/** Frame delimiter — every message starts with this byte */
|
|
5
|
+
export const MSG_START = 0x1B;
|
|
6
|
+
/** Token — separates the 4-byte header from the message body */
|
|
7
|
+
export const MSG_TOKEN = 0x0E;
|
|
8
|
+
/** Command bytes sent by the master (programmer) */
|
|
9
|
+
export const Cmd = {
|
|
10
|
+
// ── General ────────────────────────────────────────────────────────────
|
|
11
|
+
SIGN_ON: 0x01,
|
|
12
|
+
SET_PARAMETER: 0x02,
|
|
13
|
+
GET_PARAMETER: 0x03,
|
|
14
|
+
SET_DEVICE_DESCRIPTOR: 0x04,
|
|
15
|
+
OSCCAL: 0x05,
|
|
16
|
+
LOAD_ADDRESS: 0x06,
|
|
17
|
+
FIRMWARE_UPGRADE: 0x07,
|
|
18
|
+
// ── ISP programming ────────────────────────────────────────────────────
|
|
19
|
+
ENTER_PROGMODE_ISP: 0x10,
|
|
20
|
+
LEAVE_PROGMODE_ISP: 0x11,
|
|
21
|
+
CHIP_ERASE_ISP: 0x12,
|
|
22
|
+
PROGRAM_FLASH_ISP: 0x13,
|
|
23
|
+
READ_FLASH_ISP: 0x14,
|
|
24
|
+
PROGRAM_EEPROM_ISP: 0x15,
|
|
25
|
+
READ_EEPROM_ISP: 0x16,
|
|
26
|
+
PROGRAM_FUSE_ISP: 0x17,
|
|
27
|
+
READ_FUSE_ISP: 0x18,
|
|
28
|
+
PROGRAM_LOCK_ISP: 0x19,
|
|
29
|
+
READ_LOCK_ISP: 0x1A,
|
|
30
|
+
READ_SIGNATURE_ISP: 0x1B,
|
|
31
|
+
READ_OSCCAL_ISP: 0x1C,
|
|
32
|
+
SPI_MULTI: 0x1D,
|
|
33
|
+
};
|
|
34
|
+
/** Status codes returned in response bodies */
|
|
35
|
+
export const Status = {
|
|
36
|
+
CMD_OK: 0x00,
|
|
37
|
+
CMD_TOUT: 0x80, // Timeout
|
|
38
|
+
RDY_BSY_TOUT: 0x81, // Ready/busy timeout
|
|
39
|
+
SET_PARAM_MISSING: 0x82,
|
|
40
|
+
CMD_FAILED: 0xC0,
|
|
41
|
+
CMD_UNKNOWN: 0xC9,
|
|
42
|
+
ISP_READY: 0x00, // Alias for CMD_OK in ISP context
|
|
43
|
+
};
|
|
44
|
+
/** Programmer parameter IDs (used with SET/GET_PARAMETER) */
|
|
45
|
+
export const Param = {
|
|
46
|
+
BUILD_NUMBER_LOW: 0x80,
|
|
47
|
+
BUILD_NUMBER_HIGH: 0x81,
|
|
48
|
+
HW_VER: 0x90,
|
|
49
|
+
SW_MAJOR: 0x91,
|
|
50
|
+
SW_MINOR: 0x92,
|
|
51
|
+
VTARGET: 0x94,
|
|
52
|
+
VADJUST: 0x95,
|
|
53
|
+
OSC_PSCALE: 0x96,
|
|
54
|
+
OSC_CMATCH: 0x97,
|
|
55
|
+
SCK_DURATION: 0x98,
|
|
56
|
+
TOPCARD_DETECT: 0x9A,
|
|
57
|
+
STATUS: 0x9C,
|
|
58
|
+
DATA: 0x9D,
|
|
59
|
+
RESET_POLARITY: 0x9E,
|
|
60
|
+
CONTROLLER_INIT: 0x9F,
|
|
61
|
+
};
|
|
62
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/protocol/stk500v2/constants.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,sEAAsE;AACtE,2EAA2E;AAE3E,4DAA4D;AAC5D,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,CAAC;AAC9B,gEAAgE;AAChE,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,CAAC;AAE9B,oDAAoD;AACpD,MAAM,CAAC,MAAM,GAAG,GAAG;IACjB,0EAA0E;IAC1E,OAAO,EAAmB,IAAI;IAC9B,aAAa,EAAa,IAAI;IAC9B,aAAa,EAAa,IAAI;IAC9B,qBAAqB,EAAK,IAAI;IAC9B,MAAM,EAAoB,IAAI;IAC9B,YAAY,EAAc,IAAI;IAC9B,gBAAgB,EAAU,IAAI;IAE9B,0EAA0E;IAC1E,kBAAkB,EAAQ,IAAI;IAC9B,kBAAkB,EAAQ,IAAI;IAC9B,cAAc,EAAY,IAAI;IAC9B,iBAAiB,EAAS,IAAI;IAC9B,cAAc,EAAY,IAAI;IAC9B,kBAAkB,EAAQ,IAAI;IAC9B,eAAe,EAAW,IAAI;IAC9B,gBAAgB,EAAU,IAAI;IAC9B,aAAa,EAAa,IAAI;IAC9B,gBAAgB,EAAU,IAAI;IAC9B,aAAa,EAAa,IAAI;IAC9B,kBAAkB,EAAQ,IAAI;IAC9B,eAAe,EAAW,IAAI;IAC9B,SAAS,EAAiB,IAAI;CACtB,CAAC;AAEX,+CAA+C;AAC/C,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,MAAM,EAAa,IAAI;IACvB,QAAQ,EAAW,IAAI,EAAG,UAAU;IACpC,YAAY,EAAO,IAAI,EAAG,qBAAqB;IAC/C,iBAAiB,EAAE,IAAI;IACvB,UAAU,EAAS,IAAI;IACvB,WAAW,EAAQ,IAAI;IACvB,SAAS,EAAU,IAAI,EAAG,kCAAkC;CACpD,CAAC;AAEX,6DAA6D;AAC7D,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,gBAAgB,EAAI,IAAI;IACxB,iBAAiB,EAAG,IAAI;IACxB,MAAM,EAAc,IAAI;IACxB,QAAQ,EAAY,IAAI;IACxB,QAAQ,EAAY,IAAI;IACxB,OAAO,EAAa,IAAI;IACxB,OAAO,EAAa,IAAI;IACxB,UAAU,EAAU,IAAI;IACxB,UAAU,EAAU,IAAI;IACxB,YAAY,EAAQ,IAAI;IACxB,cAAc,EAAM,IAAI;IACxB,MAAM,EAAc,IAAI;IACxB,IAAI,EAAgB,IAAI;IACxB,cAAc,EAAM,IAAI;IACxB,eAAe,EAAK,IAAI;CAChB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ISTKTransport } from '../../transport/ITransport.js';
|
|
2
|
+
/**
|
|
3
|
+
* Build a complete STK500v2 frame for the given sequence number and body bytes.
|
|
4
|
+
* Body must be ≤ 65535 bytes (uint16 size field).
|
|
5
|
+
*/
|
|
6
|
+
export declare function encodeFrame(seq: number, body: number[] | Uint8Array): Uint8Array;
|
|
7
|
+
/**
|
|
8
|
+
* Wait for one complete STK500v2 frame on the transport and return its body bytes.
|
|
9
|
+
* Silently discards any bytes before MSG_START.
|
|
10
|
+
* Rejects with STK500TimeoutError if no valid frame arrives within timeoutMs.
|
|
11
|
+
* Rejects with STK500ProtocolError if the token or checksum is wrong.
|
|
12
|
+
*/
|
|
13
|
+
export declare function receiveFrame(transport: ISTKTransport, timeoutMs: number): Promise<Uint8Array>;
|
|
14
|
+
//# sourceMappingURL=frame.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frame.d.ts","sourceRoot":"","sources":["../../../src/protocol/stk500v2/frame.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAInE;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,GAAG,UAAU,CAmBhF;AAID;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,aAAa,EACxB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,UAAU,CAAC,CA6ErB"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
// STK500v2 message framing utilities.
|
|
2
|
+
//
|
|
3
|
+
// Frame format:
|
|
4
|
+
// [MSG_START(0x1B)] [SEQ] [SIZE_H] [SIZE_L] [TOKEN(0x0E)] [BODY...] [CHECKSUM]
|
|
5
|
+
//
|
|
6
|
+
// Checksum = XOR of every byte from MSG_START through the last body byte.
|
|
7
|
+
//
|
|
8
|
+
// Both encode and decode are stateless — sequence tracking lives in the programmer.
|
|
9
|
+
import { MSG_START, MSG_TOKEN } from './constants.js';
|
|
10
|
+
import { STK500TimeoutError, STK500ProtocolError } from '../../core/errors.js';
|
|
11
|
+
// ── Encode ─────────────────────────────────────────────────────────────────
|
|
12
|
+
/**
|
|
13
|
+
* Build a complete STK500v2 frame for the given sequence number and body bytes.
|
|
14
|
+
* Body must be ≤ 65535 bytes (uint16 size field).
|
|
15
|
+
*/
|
|
16
|
+
export function encodeFrame(seq, body) {
|
|
17
|
+
const size = body.length;
|
|
18
|
+
const frame = new Uint8Array(6 + size); // header(5) + body(size) + checksum(1)
|
|
19
|
+
frame[0] = MSG_START;
|
|
20
|
+
frame[1] = seq & 0xFF;
|
|
21
|
+
frame[2] = (size >> 8) & 0xFF;
|
|
22
|
+
frame[3] = size & 0xFF;
|
|
23
|
+
frame[4] = MSG_TOKEN;
|
|
24
|
+
for (let i = 0; i < size; i++) {
|
|
25
|
+
frame[5 + i] = body[i]; // works for both number[] and Uint8Array
|
|
26
|
+
}
|
|
27
|
+
let checksum = 0;
|
|
28
|
+
for (let i = 0; i < 5 + size; i++)
|
|
29
|
+
checksum ^= frame[i];
|
|
30
|
+
frame[5 + size] = checksum;
|
|
31
|
+
return frame;
|
|
32
|
+
}
|
|
33
|
+
// ── Decode ─────────────────────────────────────────────────────────────────
|
|
34
|
+
/**
|
|
35
|
+
* Wait for one complete STK500v2 frame on the transport and return its body bytes.
|
|
36
|
+
* Silently discards any bytes before MSG_START.
|
|
37
|
+
* Rejects with STK500TimeoutError if no valid frame arrives within timeoutMs.
|
|
38
|
+
* Rejects with STK500ProtocolError if the token or checksum is wrong.
|
|
39
|
+
*/
|
|
40
|
+
export function receiveFrame(transport, timeoutMs) {
|
|
41
|
+
return new Promise((resolve, reject) => {
|
|
42
|
+
let settled = false;
|
|
43
|
+
const chunks = [];
|
|
44
|
+
let totalBytes = 0;
|
|
45
|
+
const timer = setTimeout(() => {
|
|
46
|
+
if (settled)
|
|
47
|
+
return;
|
|
48
|
+
settled = true;
|
|
49
|
+
transport.off('data', onData);
|
|
50
|
+
reject(new STK500TimeoutError(timeoutMs, 'STK500v2 response'));
|
|
51
|
+
}, timeoutMs);
|
|
52
|
+
const finish = (err, data) => {
|
|
53
|
+
if (settled)
|
|
54
|
+
return;
|
|
55
|
+
settled = true;
|
|
56
|
+
clearTimeout(timer);
|
|
57
|
+
transport.off('data', onData);
|
|
58
|
+
if (err)
|
|
59
|
+
reject(err);
|
|
60
|
+
else
|
|
61
|
+
resolve(data);
|
|
62
|
+
};
|
|
63
|
+
const onData = (chunk) => {
|
|
64
|
+
if (settled)
|
|
65
|
+
return;
|
|
66
|
+
chunks.push(chunk.slice()); // defensive copy
|
|
67
|
+
totalBytes += chunk.length;
|
|
68
|
+
tryParse();
|
|
69
|
+
};
|
|
70
|
+
const tryParse = () => {
|
|
71
|
+
// Flatten accumulated chunks into one contiguous buffer
|
|
72
|
+
const buf = new Uint8Array(totalBytes);
|
|
73
|
+
let off = 0;
|
|
74
|
+
for (const c of chunks) {
|
|
75
|
+
buf.set(c, off);
|
|
76
|
+
off += c.length;
|
|
77
|
+
}
|
|
78
|
+
// Locate MSG_START
|
|
79
|
+
let startIdx = -1;
|
|
80
|
+
for (let i = 0; i < buf.length; i++) {
|
|
81
|
+
if (buf[i] === MSG_START) {
|
|
82
|
+
startIdx = i;
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (startIdx < 0)
|
|
87
|
+
return; // No start byte yet
|
|
88
|
+
// Need at least 5 bytes for the full header
|
|
89
|
+
if (buf.length - startIdx < 5)
|
|
90
|
+
return;
|
|
91
|
+
// Validate TOKEN at position +4
|
|
92
|
+
if (buf[startIdx + 4] !== MSG_TOKEN) {
|
|
93
|
+
finish(new STK500ProtocolError(`STK500v2: invalid token 0x${buf[startIdx + 4].toString(16).padStart(2, '0')}, ` +
|
|
94
|
+
`expected 0x0E at position ${startIdx + 4}`));
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
const msgSize = (buf[startIdx + 2] << 8) | buf[startIdx + 3];
|
|
98
|
+
const totalNeeded = startIdx + 5 + msgSize + 1; // header + body + checksum
|
|
99
|
+
if (buf.length < totalNeeded)
|
|
100
|
+
return; // Not enough data yet — wait
|
|
101
|
+
// Verify XOR checksum over everything from MSG_START to end of body
|
|
102
|
+
let checksum = 0;
|
|
103
|
+
for (let i = startIdx; i < totalNeeded - 1; i++)
|
|
104
|
+
checksum ^= buf[i];
|
|
105
|
+
if (checksum !== buf[totalNeeded - 1]) {
|
|
106
|
+
finish(new STK500ProtocolError(`STK500v2: checksum mismatch — ` +
|
|
107
|
+
`computed 0x${checksum.toString(16).padStart(2, '0')}, ` +
|
|
108
|
+
`received 0x${buf[totalNeeded - 1].toString(16).padStart(2, '0')}`));
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
finish(undefined, buf.slice(startIdx + 5, startIdx + 5 + msgSize));
|
|
112
|
+
};
|
|
113
|
+
transport.on('data', onData);
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=frame.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frame.js","sourceRoot":"","sources":["../../../src/protocol/stk500v2/frame.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { Board, STK500Options, BootloadProgressCallback } from '../../core/types.js';
|
|
2
|
+
import type { ISTKTransport } from '../../transport/ITransport.js';
|
|
3
|
+
export declare class STK500v2 {
|
|
4
|
+
private readonly transport;
|
|
5
|
+
private readonly board;
|
|
6
|
+
private seq;
|
|
7
|
+
private readonly log;
|
|
8
|
+
private readonly syncAttempts;
|
|
9
|
+
private readonly retryDelayMs;
|
|
10
|
+
constructor(transport: ISTKTransport, board: Board, opts?: STK500Options);
|
|
11
|
+
/**
|
|
12
|
+
* Send a command body and return the full response body.
|
|
13
|
+
* Throws STK500ProtocolError when the device reports failure.
|
|
14
|
+
*/
|
|
15
|
+
private send;
|
|
16
|
+
resetDevice(): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Send CMD_SIGN_ON and return the bootloader name string (e.g. "AVRISP_MK2").
|
|
19
|
+
* Throws on timeout or framing error.
|
|
20
|
+
*/
|
|
21
|
+
signOn(): Promise<string>;
|
|
22
|
+
sync(attempts: number): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Send CMD_SET_DEVICE_DESCRIPTOR (0x04).
|
|
25
|
+
* Most wiring-bootloader implementations accept any 52-byte body.
|
|
26
|
+
* Key fields are flash/EEPROM page sizes and boot address.
|
|
27
|
+
*/
|
|
28
|
+
setDeviceDescriptor(): Promise<void>;
|
|
29
|
+
enterProgMode(): Promise<void>;
|
|
30
|
+
leaveProgMode(): Promise<void>;
|
|
31
|
+
chipErase(): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* CMD_LOAD_ADDRESS — sets the current flash address for subsequent reads/writes.
|
|
34
|
+
* Address is in WORDS (byte_address / 2).
|
|
35
|
+
* For addresses > 65535 words (>128KB), bit 31 is set to indicate extended mode.
|
|
36
|
+
*/
|
|
37
|
+
loadAddress(wordAddr: number): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Write one flash page (CMD_PROGRAM_FLASH_ISP).
|
|
40
|
+
* @param wordAddr Word address of the page start
|
|
41
|
+
* @param data Page data (must be ≤ board.pageSize bytes)
|
|
42
|
+
*/
|
|
43
|
+
programFlash(wordAddr: number, data: Uint8Array): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Read one flash page (CMD_READ_FLASH_ISP).
|
|
46
|
+
* @param wordAddr Word address of the page start
|
|
47
|
+
* @param size Number of BYTES to read
|
|
48
|
+
* @returns The raw flash bytes
|
|
49
|
+
*/
|
|
50
|
+
readFlash(wordAddr: number, size: number): Promise<Uint8Array>;
|
|
51
|
+
/**
|
|
52
|
+
* Read the 3-byte device signature via three CMD_READ_SIGNATURE_ISP calls.
|
|
53
|
+
*/
|
|
54
|
+
readSignature(): Promise<Uint8Array>;
|
|
55
|
+
verifySignature(): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Read one fuse byte via CMD_READ_FUSE_ISP (0x18).
|
|
58
|
+
* @param fuseType Which fuse: 'low' | 'high' | 'ext' | 'lock'
|
|
59
|
+
*/
|
|
60
|
+
readFuseIsp(fuseType: 'low' | 'high' | 'ext' | 'lock'): Promise<number>;
|
|
61
|
+
/**
|
|
62
|
+
* Read all four fuse/lock bytes in one call.
|
|
63
|
+
*/
|
|
64
|
+
readFuses(): Promise<{
|
|
65
|
+
low: number;
|
|
66
|
+
high: number;
|
|
67
|
+
ext: number;
|
|
68
|
+
lock: number;
|
|
69
|
+
}>;
|
|
70
|
+
/**
|
|
71
|
+
* Write a fuse byte via CMD_PROGRAM_FUSE_ISP (0x17).
|
|
72
|
+
* @param fuseType Which fuse: 'low' | 'high' | 'ext'
|
|
73
|
+
* @param val New fuse value
|
|
74
|
+
*/
|
|
75
|
+
writeFuseIsp(fuseType: 'low' | 'high' | 'ext', val: number): Promise<void>;
|
|
76
|
+
/**
|
|
77
|
+
* Write EEPROM data via CMD_PROGRAM_EEPROM_ISP (0x15).
|
|
78
|
+
* @param byteAddr Byte address in EEPROM
|
|
79
|
+
* @param data Data bytes (length ≤ eepromPageSize, default 8)
|
|
80
|
+
*/
|
|
81
|
+
programEeprom(byteAddr: number, data: Uint8Array): Promise<void>;
|
|
82
|
+
/**
|
|
83
|
+
* Read EEPROM data via CMD_READ_EEPROM_ISP (0x16).
|
|
84
|
+
* @param byteAddr Byte address in EEPROM
|
|
85
|
+
* @param size Number of bytes to read
|
|
86
|
+
*/
|
|
87
|
+
readEeprom(byteAddr: number, size: number): Promise<Uint8Array>;
|
|
88
|
+
upload(hexData: string | Uint8Array, progressCallback?: (pct: number) => void): Promise<void>;
|
|
89
|
+
verify(hexData: string | Uint8Array, progressCallback?: (pct: number) => void): Promise<void>;
|
|
90
|
+
bootload(hexData: string | Uint8Array, progressCallback?: BootloadProgressCallback): Promise<void>;
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=programmer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"programmer.d.ts","sourceRoot":"","sources":["../../../src/protocol/stk500v2/programmer.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EACV,KAAK,EACL,aAAa,EACb,wBAAwB,EAEzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAOnE,qBAAa,QAAQ;IAOjB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,KAAK;IAPxB,OAAO,CAAC,GAAG,CAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;gBAGnB,SAAS,EAAE,aAAa,EACxB,KAAK,EAAE,KAAK,EAC7B,IAAI,GAAE,aAAkB;IAqB1B;;;OAGG;YACW,IAAI;IA+BZ,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAqBlC;;;OAGG;IACG,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;IAYzB,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqB3C;;;;OAIG;IACG,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IAWpC,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAgB9B,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAO9B,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAehC;;;;OAIG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBlD;;;;OAIG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAwBrE;;;;;OAKG;IACG,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAiBpE;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,UAAU,CAAC;IAmBpC,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAetC;;;OAGG;IACG,WAAW,CAAC,QAAQ,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAoB7E;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IASpF;;;;OAIG;IACG,YAAY,CAAC,QAAQ,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBhF;;;;OAIG;IACG,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IA4BtE;;;;OAIG;IACG,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAgB/D,MAAM,CACV,OAAO,EAAE,MAAM,GAAG,UAAU,EAC5B,gBAAgB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GACvC,OAAO,CAAC,IAAI,CAAC;IAyBV,MAAM,CACV,OAAO,EAAE,MAAM,GAAG,UAAU,EAC5B,gBAAgB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GACvC,OAAO,CAAC,IAAI,CAAC;IAyBV,QAAQ,CACZ,OAAO,EAAE,MAAM,GAAG,UAAU,EAC5B,gBAAgB,CAAC,EAAE,wBAAwB,GAC1C,OAAO,CAAC,IAAI,CAAC;CAuCjB"}
|