@onekeyfe/hd-transport 1.2.0-alpha.1 → 1.2.0-alpha.11
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/README.md +1 -1
- package/__tests__/messages.test.js +76 -0
- package/__tests__/protocol-v2-link-manager.test.js +326 -0
- package/__tests__/protocol-v2-usb-transport-base.test.js +296 -0
- package/__tests__/protocol-v2.test.js +249 -81
- package/dist/constants.d.ts +4 -2
- package/dist/constants.d.ts.map +1 -1
- package/dist/index.d.ts +547 -235
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +442 -72
- package/dist/protocols/index.d.ts +2 -0
- package/dist/protocols/index.d.ts.map +1 -1
- package/dist/protocols/v2/constants.d.ts +1 -0
- package/dist/protocols/v2/constants.d.ts.map +1 -1
- package/dist/protocols/v2/decode.d.ts +1 -0
- package/dist/protocols/v2/decode.d.ts.map +1 -1
- package/dist/protocols/v2/link-manager.d.ts +35 -0
- package/dist/protocols/v2/link-manager.d.ts.map +1 -0
- package/dist/protocols/v2/sequence-cursor.d.ts +5 -0
- package/dist/protocols/v2/sequence-cursor.d.ts.map +1 -0
- package/dist/protocols/v2/session.d.ts +16 -4
- package/dist/protocols/v2/session.d.ts.map +1 -1
- package/dist/protocols/v2/usb-transport-base.d.ts +31 -0
- package/dist/protocols/v2/usb-transport-base.d.ts.map +1 -0
- package/dist/serialization/protobuf/messages.d.ts.map +1 -1
- package/dist/types/messages.d.ts +329 -156
- package/dist/types/messages.d.ts.map +1 -1
- package/dist/types/transport.d.ts +1 -1
- package/dist/types/transport.d.ts.map +1 -1
- package/messages-protocol-v2.json +760 -1110
- package/package.json +2 -2
- package/scripts/protobuf-build.sh +60 -142
- package/src/constants.ts +8 -2
- package/src/index.ts +8 -0
- package/src/protocols/index.ts +4 -1
- package/src/protocols/v2/constants.ts +1 -0
- package/src/protocols/v2/decode.ts +36 -17
- package/src/protocols/v2/link-manager.ts +160 -0
- package/src/protocols/v2/sequence-cursor.ts +10 -0
- package/src/protocols/v2/session.ts +80 -45
- package/src/protocols/v2/usb-transport-base.ts +194 -0
- package/src/serialization/protobuf/messages.ts +6 -1
- package/src/types/messages.ts +401 -186
- package/src/types/transport.ts +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { PROTOCOL_V2_PACKET_SRC_COMMAND } from '../../constants';
|
|
2
2
|
import { ProtocolV2FrameAssembler, concatUint8Arrays } from './frame-assembler';
|
|
3
|
-
import {
|
|
3
|
+
import { ProtocolV2SequenceCursor } from './sequence-cursor';
|
|
4
4
|
import { ProtocolV2 } from '..';
|
|
5
5
|
import * as check from '../../utils/highlevel-checks';
|
|
6
6
|
import { LogBlockCommand } from '../../utils/logBlockCommand';
|
|
@@ -13,6 +13,13 @@ export type ProtocolV2Schemas = {
|
|
|
13
13
|
protocolV2: Root;
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
+
export type ProtocolV2CallContext = {
|
|
17
|
+
messageName: string;
|
|
18
|
+
timeoutMs?: number;
|
|
19
|
+
highVolume: boolean;
|
|
20
|
+
generation: number;
|
|
21
|
+
};
|
|
22
|
+
|
|
16
23
|
type ProtocolLogger = {
|
|
17
24
|
debug?: (...args: any[]) => void;
|
|
18
25
|
error?: (...args: any[]) => void;
|
|
@@ -22,11 +29,15 @@ export type ProtocolV2SessionOptions = {
|
|
|
22
29
|
schemas: ProtocolV2Schemas;
|
|
23
30
|
router: number;
|
|
24
31
|
packetSrc?: number;
|
|
25
|
-
|
|
26
|
-
|
|
32
|
+
maxFrameBytes?: number;
|
|
33
|
+
prepareCall?: (context: ProtocolV2CallContext) => Promise<void> | void;
|
|
34
|
+
writeFrame: (frame: Uint8Array, context: ProtocolV2CallContext) => Promise<void>;
|
|
35
|
+
readFrame: (context: ProtocolV2CallContext) => Promise<Uint8Array>;
|
|
27
36
|
logger?: ProtocolLogger;
|
|
28
37
|
logPrefix?: string;
|
|
29
38
|
createTimeoutError?: (name: string, timeoutMs: number) => Error;
|
|
39
|
+
sequenceCursor?: ProtocolV2SequenceCursor;
|
|
40
|
+
generation?: number;
|
|
30
41
|
};
|
|
31
42
|
|
|
32
43
|
export type ProtocolV2CallOptions = {
|
|
@@ -37,6 +48,7 @@ export type ProtocolV2CallOptions = {
|
|
|
37
48
|
};
|
|
38
49
|
|
|
39
50
|
export { concatUint8Arrays, ProtocolV2FrameAssembler };
|
|
51
|
+
export { ProtocolV2SequenceCursor };
|
|
40
52
|
|
|
41
53
|
export function hexToBytes(hex: string): Uint8Array {
|
|
42
54
|
const clean = hex.replace(/\s+/g, '');
|
|
@@ -229,24 +241,23 @@ export async function withProtocolTimeout<T>(
|
|
|
229
241
|
}
|
|
230
242
|
}
|
|
231
243
|
|
|
232
|
-
//
|
|
233
|
-
//
|
|
234
|
-
//
|
|
235
|
-
|
|
236
|
-
export const PROTOCOL_V2_WRITE_WATCHDOG_TIMEOUT_MS = 30000;
|
|
244
|
+
// Write completion is owned by the concrete transport. A Promise.race watchdog
|
|
245
|
+
// here can return while libusb/WebUSB is still flushing a large Protocol V2
|
|
246
|
+
// frame, which desynchronizes later request/response pairs.
|
|
247
|
+
export const PROTOCOL_V2_WRITE_WATCHDOG_TIMEOUT_MS = 0;
|
|
237
248
|
|
|
238
249
|
export class ProtocolV2Session {
|
|
239
250
|
private readonly options: ProtocolV2SessionOptions;
|
|
240
251
|
|
|
252
|
+
private readonly sequenceCursor: ProtocolV2SequenceCursor;
|
|
253
|
+
|
|
241
254
|
// Serializes call() invocations: responses are matched only by type, so two
|
|
242
255
|
// in-flight calls on the same session would steal each other's responses.
|
|
243
256
|
private pendingCall: Promise<unknown> = Promise.resolve();
|
|
244
257
|
|
|
245
|
-
// Per-session sequence counter (1-255, wraps skipping 0).
|
|
246
|
-
private protoSeq = 0;
|
|
247
|
-
|
|
248
258
|
constructor(options: ProtocolV2SessionOptions) {
|
|
249
259
|
this.options = options;
|
|
260
|
+
this.sequenceCursor = options.sequenceCursor ?? new ProtocolV2SequenceCursor();
|
|
250
261
|
}
|
|
251
262
|
|
|
252
263
|
call(
|
|
@@ -271,25 +282,41 @@ export class ProtocolV2Session {
|
|
|
271
282
|
schemas,
|
|
272
283
|
router,
|
|
273
284
|
packetSrc = PROTOCOL_V2_PACKET_SRC_COMMAND,
|
|
285
|
+
maxFrameBytes,
|
|
286
|
+
prepareCall,
|
|
274
287
|
writeFrame,
|
|
275
288
|
readFrame,
|
|
276
289
|
logger,
|
|
277
290
|
logPrefix = 'ProtocolV2',
|
|
278
291
|
createTimeoutError,
|
|
292
|
+
generation = 0,
|
|
279
293
|
} = this.options;
|
|
280
294
|
|
|
281
295
|
const shouldReduceDebug = shouldReduceProtocolV2Debug(name);
|
|
282
|
-
|
|
296
|
+
const callContext: ProtocolV2CallContext = {
|
|
297
|
+
messageName: name,
|
|
298
|
+
timeoutMs: callOptions.timeoutMs,
|
|
299
|
+
highVolume: shouldReduceDebug,
|
|
300
|
+
generation,
|
|
301
|
+
};
|
|
302
|
+
await prepareCall?.(callContext);
|
|
303
|
+
const protoSeq = this.sequenceCursor.next();
|
|
283
304
|
const frame = ProtocolV2.encodeFrame(schemas, name, data, {
|
|
284
305
|
packetSrc,
|
|
285
306
|
router,
|
|
286
|
-
seq:
|
|
307
|
+
seq: protoSeq,
|
|
287
308
|
logger: shouldReduceDebug ? undefined : logger,
|
|
288
309
|
logPrefix,
|
|
289
310
|
context: `tx:${name}`,
|
|
290
311
|
});
|
|
291
312
|
const expectedSeq = frame[6];
|
|
292
313
|
|
|
314
|
+
if (maxFrameBytes !== undefined && frame.length > maxFrameBytes) {
|
|
315
|
+
throw new Error(
|
|
316
|
+
`Protocol V2 frame too large for transport: ${frame.length} > ${maxFrameBytes}`
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
|
|
293
320
|
if (!shouldReduceDebug) {
|
|
294
321
|
logger?.debug?.(
|
|
295
322
|
`[${logPrefix}] TX payload name=${name}`,
|
|
@@ -305,7 +332,7 @@ export class ProtocolV2Session {
|
|
|
305
332
|
// Lenient watchdog on the write phase only — see
|
|
306
333
|
// PROTOCOL_V2_WRITE_WATCHDOG_TIMEOUT_MS for the rationale.
|
|
307
334
|
await withProtocolTimeout(
|
|
308
|
-
writeFrame(frame),
|
|
335
|
+
writeFrame(frame, callContext),
|
|
309
336
|
PROTOCOL_V2_WRITE_WATCHDOG_TIMEOUT_MS,
|
|
310
337
|
() =>
|
|
311
338
|
new Error(
|
|
@@ -324,7 +351,7 @@ export class ProtocolV2Session {
|
|
|
324
351
|
// terminal response. Consume those frames here so callers still see a
|
|
325
352
|
// request/terminal-response shaped API.
|
|
326
353
|
while (!cancellation.cancelled) {
|
|
327
|
-
const rxFrame = await readFrame();
|
|
354
|
+
const rxFrame = await readFrame(callContext);
|
|
328
355
|
if (cancellation.cancelled) {
|
|
329
356
|
// Timed out while waiting: drop the late frame and stop reading.
|
|
330
357
|
break;
|
|
@@ -336,37 +363,45 @@ export class ProtocolV2Session {
|
|
|
336
363
|
} seq=${rxFrame[6]} headerHex=${frameHeaderDebugHex(rxFrame)}`
|
|
337
364
|
);
|
|
338
365
|
}
|
|
339
|
-
const
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
if (!shouldReduceDebug && decoded.seq !== expectedSeq) {
|
|
345
|
-
logger?.debug?.(
|
|
346
|
-
`[${logPrefix}] seq differs for ${name}: tx=${expectedSeq}, rx=${decoded.seq}`
|
|
347
|
-
);
|
|
348
|
-
}
|
|
349
|
-
if (!shouldReduceDebug) {
|
|
350
|
-
logger?.debug?.(
|
|
351
|
-
`[${logPrefix}] TX name=${name} seq=${expectedSeq} | RX seq=${decoded.seq} messageTypeId=${decoded.messageTypeId} pbPayload=${decoded.pbPayload.length}B`
|
|
352
|
-
);
|
|
353
|
-
logger?.debug?.(
|
|
354
|
-
`[${logPrefix}] RX payload type=${decoded.type} messageTypeId=${decoded.messageTypeId}`,
|
|
355
|
-
sanitizeProtocolV2DebugPayload(decoded.message)
|
|
356
|
-
);
|
|
366
|
+
const isAck = ProtocolV2.isAckFrame(rxFrame);
|
|
367
|
+
if (isAck) {
|
|
368
|
+
if (!shouldReduceDebug) {
|
|
369
|
+
logger?.debug?.(`[${logPrefix}] skip Proto Link ACK seq=${rxFrame[6]}`);
|
|
370
|
+
}
|
|
357
371
|
}
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
)
|
|
372
|
+
if (!isAck) {
|
|
373
|
+
const decoded = ProtocolV2.decodeFrame(schemas, rxFrame, {
|
|
374
|
+
logger: shouldReduceDebug ? undefined : logger,
|
|
375
|
+
logPrefix,
|
|
376
|
+
context: `rx:${name}`,
|
|
377
|
+
});
|
|
378
|
+
if (!shouldReduceDebug && decoded.seq !== expectedSeq) {
|
|
379
|
+
logger?.debug?.(
|
|
380
|
+
`[${logPrefix}] seq differs for ${name}: tx=${expectedSeq}, rx=${decoded.seq}`
|
|
381
|
+
);
|
|
382
|
+
}
|
|
383
|
+
if (!shouldReduceDebug) {
|
|
384
|
+
logger?.debug?.(
|
|
385
|
+
`[${logPrefix}] TX name=${name} seq=${expectedSeq} | RX seq=${decoded.seq} messageTypeId=${decoded.messageTypeId} pbPayload=${decoded.pbPayload.length}B`
|
|
386
|
+
);
|
|
387
|
+
logger?.debug?.(
|
|
388
|
+
`[${logPrefix}] RX payload type=${decoded.type} messageTypeId=${decoded.messageTypeId}`,
|
|
389
|
+
sanitizeProtocolV2DebugPayload(decoded.message)
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
const response = check.call(decoded);
|
|
394
|
+
if (callOptions.intermediateTypes?.includes(response.type)) {
|
|
395
|
+
callOptions.onIntermediateResponse?.(response);
|
|
396
|
+
} else if (isExpectedTerminalResponse(response, callOptions.expectedTypes)) {
|
|
397
|
+
return response;
|
|
398
|
+
} else if (!shouldReduceDebug) {
|
|
399
|
+
logger?.debug?.(
|
|
400
|
+
`[${logPrefix}] skip unexpected response for ${name}: expected=${callOptions.expectedTypes?.join(
|
|
401
|
+
'|'
|
|
402
|
+
)} got=${response.type}`
|
|
403
|
+
);
|
|
404
|
+
}
|
|
370
405
|
}
|
|
371
406
|
}
|
|
372
407
|
// Only reachable after cancellation; the outer promise has already been
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { ProtocolV2FrameAssembler } from './frame-assembler';
|
|
2
|
+
import { ProtocolV2LinkManager } from './link-manager';
|
|
3
|
+
|
|
4
|
+
import type { MessageFromOneKey, TransportCallOptions } from '../../types';
|
|
5
|
+
import type { ProtocolV2CallContext, ProtocolV2Schemas, ProtocolV2SessionOptions } from './session';
|
|
6
|
+
|
|
7
|
+
export type ProtocolV2UsbTransportBaseOptions = {
|
|
8
|
+
router: number;
|
|
9
|
+
maxFrameBytes: number;
|
|
10
|
+
logPrefix: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
type ProtocolV2UsbCancellation = {
|
|
14
|
+
generation: number;
|
|
15
|
+
reason?: string;
|
|
16
|
+
promise: Promise<string>;
|
|
17
|
+
cancel: (reason: string) => void;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export abstract class ProtocolV2UsbTransportBase<Key> {
|
|
21
|
+
private readonly protocolV2UsbLinks: ProtocolV2LinkManager<Key>;
|
|
22
|
+
|
|
23
|
+
private readonly protocolV2UsbAssemblers = new Map<Key, ProtocolV2FrameAssembler>();
|
|
24
|
+
|
|
25
|
+
private readonly protocolV2UsbGenerations = new Map<Key, number>();
|
|
26
|
+
|
|
27
|
+
private readonly protocolV2UsbCancellations = new Map<Key, ProtocolV2UsbCancellation>();
|
|
28
|
+
|
|
29
|
+
private readonly protocolV2UsbOptions: ProtocolV2UsbTransportBaseOptions;
|
|
30
|
+
|
|
31
|
+
protected constructor(options: ProtocolV2UsbTransportBaseOptions) {
|
|
32
|
+
this.protocolV2UsbOptions = options;
|
|
33
|
+
this.protocolV2UsbLinks = new ProtocolV2LinkManager<Key>({
|
|
34
|
+
getSchemas: () => this.getProtocolV2UsbSchemas(),
|
|
35
|
+
classifyError: () => 'link-fatal',
|
|
36
|
+
onLinkInvalidated: async (key, reason) => {
|
|
37
|
+
this.protocolV2UsbAssemblers.get(key)?.reset();
|
|
38
|
+
await this.resetProtocolV2UsbNativeLink(key, reason);
|
|
39
|
+
await this.onProtocolV2UsbLinkInvalidated(key, reason);
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
protected abstract getProtocolV2UsbSchemas(): ProtocolV2Schemas;
|
|
45
|
+
|
|
46
|
+
protected abstract getProtocolV2UsbLogger(): ProtocolV2SessionOptions['logger'];
|
|
47
|
+
|
|
48
|
+
protected abstract writeProtocolV2UsbPacket(
|
|
49
|
+
key: Key,
|
|
50
|
+
frame: Uint8Array,
|
|
51
|
+
context: ProtocolV2CallContext
|
|
52
|
+
): Promise<void>;
|
|
53
|
+
|
|
54
|
+
protected abstract readProtocolV2UsbPacket(
|
|
55
|
+
key: Key,
|
|
56
|
+
context: ProtocolV2CallContext
|
|
57
|
+
): Promise<Uint8Array>;
|
|
58
|
+
|
|
59
|
+
protected abstract resetProtocolV2UsbNativeLink(key: Key, reason: string): Promise<void>;
|
|
60
|
+
|
|
61
|
+
protected abstract createProtocolV2UsbTimeoutError(name: string, timeoutMs: number): Error;
|
|
62
|
+
|
|
63
|
+
protected onProtocolV2UsbLinkInvalidated(_key: Key, _reason: string): Promise<void> | void {
|
|
64
|
+
// 子类按需清理协议缓存或记录平台日志。
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
protected async rotateProtocolV2UsbGeneration(key: Key, reason: string): Promise<number> {
|
|
68
|
+
await this.protocolV2UsbLinks.invalidateLink(key, reason);
|
|
69
|
+
const generation = (this.protocolV2UsbGenerations.get(key) ?? 0) + 1;
|
|
70
|
+
this.protocolV2UsbGenerations.set(key, generation);
|
|
71
|
+
this.protocolV2UsbCancellations.set(key, this.createProtocolV2UsbCancellation(generation));
|
|
72
|
+
this.protocolV2UsbAssemblers.set(
|
|
73
|
+
key,
|
|
74
|
+
new ProtocolV2FrameAssembler(this.protocolV2UsbOptions.maxFrameBytes)
|
|
75
|
+
);
|
|
76
|
+
return generation;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
protected callProtocolV2Usb(
|
|
80
|
+
key: Key,
|
|
81
|
+
name: string,
|
|
82
|
+
data: Record<string, unknown>,
|
|
83
|
+
options?: TransportCallOptions
|
|
84
|
+
): Promise<MessageFromOneKey> {
|
|
85
|
+
return this.protocolV2UsbLinks.call(
|
|
86
|
+
key,
|
|
87
|
+
() => this.createProtocolV2UsbAdapter(key),
|
|
88
|
+
name,
|
|
89
|
+
data,
|
|
90
|
+
options
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
protected invalidateProtocolV2UsbLink(key: Key, reason: string): Promise<void> {
|
|
95
|
+
return this.protocolV2UsbLinks.invalidateLink(key, reason);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
protected invalidateAllProtocolV2UsbLinks(reason: string): Promise<void> {
|
|
99
|
+
return this.protocolV2UsbLinks.invalidateAllLinks(reason);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
protected async disposeProtocolV2UsbLinks(reason: string): Promise<void> {
|
|
103
|
+
await this.protocolV2UsbLinks.dispose(reason);
|
|
104
|
+
this.protocolV2UsbAssemblers.clear();
|
|
105
|
+
this.protocolV2UsbGenerations.clear();
|
|
106
|
+
this.protocolV2UsbCancellations.clear();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
private createProtocolV2UsbAdapter(key: Key) {
|
|
110
|
+
const generation = this.protocolV2UsbGenerations.get(key);
|
|
111
|
+
if (generation === undefined) {
|
|
112
|
+
throw new Error('Protocol V2 USB generation has not been initialized');
|
|
113
|
+
}
|
|
114
|
+
const cancellation = this.protocolV2UsbCancellations.get(key);
|
|
115
|
+
if (!cancellation || cancellation.generation !== generation) {
|
|
116
|
+
throw new Error('Protocol V2 USB cancellation state has not been initialized');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const assertCurrentGeneration = () => {
|
|
120
|
+
if (cancellation.reason) {
|
|
121
|
+
throw new Error(cancellation.reason);
|
|
122
|
+
}
|
|
123
|
+
if (this.protocolV2UsbGenerations.get(key) !== generation) {
|
|
124
|
+
throw new Error('Protocol V2 USB connection generation changed');
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
return {
|
|
129
|
+
router: this.protocolV2UsbOptions.router,
|
|
130
|
+
maxFrameBytes: this.protocolV2UsbOptions.maxFrameBytes,
|
|
131
|
+
generation,
|
|
132
|
+
prepareCall: () => {
|
|
133
|
+
assertCurrentGeneration();
|
|
134
|
+
this.getProtocolV2UsbAssembler(key).reset();
|
|
135
|
+
},
|
|
136
|
+
writeFrame: async (frame: Uint8Array, context: ProtocolV2CallContext) => {
|
|
137
|
+
assertCurrentGeneration();
|
|
138
|
+
await this.writeProtocolV2UsbPacket(key, frame, context);
|
|
139
|
+
assertCurrentGeneration();
|
|
140
|
+
},
|
|
141
|
+
readFrame: async (context: ProtocolV2CallContext) => {
|
|
142
|
+
assertCurrentGeneration();
|
|
143
|
+
const assembler = this.getProtocolV2UsbAssembler(key);
|
|
144
|
+
let frame = assembler.push(new Uint8Array(0));
|
|
145
|
+
while (!frame) {
|
|
146
|
+
const packetRead = this.readProtocolV2UsbPacket(key, context).then(packet => ({
|
|
147
|
+
packet,
|
|
148
|
+
}));
|
|
149
|
+
const cancelled = cancellation.promise.then(reason => ({ reason }));
|
|
150
|
+
const result = await Promise.race([packetRead, cancelled]);
|
|
151
|
+
if ('reason' in result) {
|
|
152
|
+
throw new Error(result.reason);
|
|
153
|
+
}
|
|
154
|
+
assertCurrentGeneration();
|
|
155
|
+
frame = assembler.push(result.packet);
|
|
156
|
+
}
|
|
157
|
+
assertCurrentGeneration();
|
|
158
|
+
return frame;
|
|
159
|
+
},
|
|
160
|
+
reset: (reason: string) => {
|
|
161
|
+
cancellation.cancel(reason);
|
|
162
|
+
this.protocolV2UsbAssemblers.get(key)?.reset();
|
|
163
|
+
},
|
|
164
|
+
logger: this.getProtocolV2UsbLogger(),
|
|
165
|
+
logPrefix: this.protocolV2UsbOptions.logPrefix,
|
|
166
|
+
createTimeoutError: (messageName: string, timeoutMs: number) =>
|
|
167
|
+
this.createProtocolV2UsbTimeoutError(messageName, timeoutMs),
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
private getProtocolV2UsbAssembler(key: Key): ProtocolV2FrameAssembler {
|
|
172
|
+
const assembler = this.protocolV2UsbAssemblers.get(key);
|
|
173
|
+
if (!assembler) {
|
|
174
|
+
throw new Error('Protocol V2 USB assembler has not been initialized');
|
|
175
|
+
}
|
|
176
|
+
return assembler;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
private createProtocolV2UsbCancellation(generation: number): ProtocolV2UsbCancellation {
|
|
180
|
+
let resolveCancellation: (reason: string) => void = () => undefined;
|
|
181
|
+
const cancellation: ProtocolV2UsbCancellation = {
|
|
182
|
+
generation,
|
|
183
|
+
promise: new Promise(resolve => {
|
|
184
|
+
resolveCancellation = resolve;
|
|
185
|
+
}),
|
|
186
|
+
cancel: reason => {
|
|
187
|
+
if (cancellation.reason) return;
|
|
188
|
+
cancellation.reason = reason;
|
|
189
|
+
resolveCancellation(reason);
|
|
190
|
+
},
|
|
191
|
+
};
|
|
192
|
+
return cancellation;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
@@ -30,7 +30,12 @@ export const createMessageFromName = (messages: protobuf.Root, name: string) =>
|
|
|
30
30
|
export const createMessageFromType = (messages: protobuf.Root, typeId: number) => {
|
|
31
31
|
const MessageType = messages.lookupEnum('MessageType');
|
|
32
32
|
|
|
33
|
-
const
|
|
33
|
+
const rawMessageName = MessageType.valuesById[typeId];
|
|
34
|
+
if (!rawMessageName) {
|
|
35
|
+
throw new Error(`MessageType id "${typeId}" is not defined in protobuf schema`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const messageName = rawMessageName.replace('MessageType_', '');
|
|
34
39
|
|
|
35
40
|
const Message = messages.lookupType(messageName);
|
|
36
41
|
|