@onekeyfe/hd-core 1.2.0-alpha.11 → 1.2.0-alpha.12
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/__tests__/protocol-v2.test.ts +114 -30
- package/__tests__/protocolV2FileWrite.test.ts +55 -0
- package/dist/api/FileWrite.d.ts.map +1 -1
- package/dist/api/helpers/protocolV2FileWrite.d.ts +32 -0
- package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -0
- package/dist/api/index.d.ts +1 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceGetOnboardingStatus.d.ts +6 -0
- package/dist/api/protocol-v2/DeviceGetOnboardingStatus.d.ts.map +1 -0
- package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts.map +1 -1
- package/dist/deviceProfile/buildDeviceFeatures.d.ts +2 -2
- package/dist/deviceProfile/buildDeviceFeatures.d.ts.map +1 -1
- package/dist/deviceProfile/buildDeviceProfile.d.ts.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.js +263 -254
- package/dist/inject.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/features.d.ts +1 -0
- package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/index.d.ts +1 -1
- package/dist/protocols/protocol-v2/index.d.ts.map +1 -1
- package/dist/types/api/getDeviceInfo.d.ts +1 -1
- package/dist/types/api/getDeviceInfo.d.ts.map +1 -1
- package/dist/types/api/index.d.ts +2 -1
- package/dist/types/api/index.d.ts.map +1 -1
- package/dist/types/api/protocolV2.d.ts +2 -1
- package/dist/types/api/protocolV2.d.ts.map +1 -1
- package/dist/types/device.d.ts +1 -1
- package/dist/types/device.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/FileWrite.ts +18 -186
- package/src/api/helpers/protocolV2FileWrite.ts +164 -0
- package/src/api/index.ts +1 -0
- package/src/api/protocol-v2/DeviceGetOnboardingStatus.ts +18 -0
- package/src/api/protocol-v2/DeviceUploadWallpaper.ts +13 -49
- package/src/deviceProfile/buildDeviceFeatures.ts +20 -12
- package/src/deviceProfile/buildDeviceProfile.ts +8 -6
- package/src/inject.ts +2 -0
- package/src/protocols/protocol-v2/features.ts +19 -1
- package/src/protocols/protocol-v2/index.ts +2 -0
- package/src/types/api/getDeviceInfo.ts +1 -1
- package/src/types/api/index.ts +2 -0
- package/src/types/api/protocolV2.ts +6 -0
- package/src/types/device.ts +1 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PROTOCOL_V2_BLE_FILE_CHUNK_SIZE,
|
|
3
|
+
PROTOCOL_V2_WEBUSB_FILE_CHUNK_SIZE,
|
|
4
|
+
} from '@onekeyfe/hd-transport';
|
|
5
|
+
import { ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
|
|
6
|
+
|
|
7
|
+
import { DataManager } from '../../data-manager';
|
|
8
|
+
|
|
9
|
+
import type { DeviceCommands } from '../../device/DeviceCommands';
|
|
10
|
+
|
|
11
|
+
export type ProtocolV2FileWriteData = ArrayBuffer | Uint8Array | Blob | string;
|
|
12
|
+
|
|
13
|
+
export type ProtocolV2FileWriteProgress = {
|
|
14
|
+
progress: number;
|
|
15
|
+
transferredBytes: number;
|
|
16
|
+
totalBytes: number;
|
|
17
|
+
rateBytesPerSecond?: number;
|
|
18
|
+
elapsedMs: number;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export type ProtocolV2FileWriteOptions = {
|
|
22
|
+
commands: Pick<DeviceCommands, 'typedCall'>;
|
|
23
|
+
path: string;
|
|
24
|
+
data: ProtocolV2FileWriteData;
|
|
25
|
+
offset?: number;
|
|
26
|
+
totalSize?: number;
|
|
27
|
+
chunkSize?: number;
|
|
28
|
+
chunkLen?: number;
|
|
29
|
+
overwrite?: boolean;
|
|
30
|
+
append?: boolean;
|
|
31
|
+
uiPercentage?: number;
|
|
32
|
+
timeoutMs?: number;
|
|
33
|
+
throwIfAborted?: () => void;
|
|
34
|
+
onProgress?: (progress: ProtocolV2FileWriteProgress) => void;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const MIN_FILE_CHUNK_SIZE = 64;
|
|
38
|
+
|
|
39
|
+
function getProtocolV2FileChunkLimit() {
|
|
40
|
+
const env = DataManager.getSettings('env');
|
|
41
|
+
return env && DataManager.isBleConnect(env)
|
|
42
|
+
? PROTOCOL_V2_BLE_FILE_CHUNK_SIZE
|
|
43
|
+
: PROTOCOL_V2_WEBUSB_FILE_CHUNK_SIZE;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function dataToUint8Array(data: ProtocolV2FileWriteData): Promise<Uint8Array> {
|
|
47
|
+
if (typeof data === 'string') return new TextEncoder().encode(data);
|
|
48
|
+
if (data instanceof ArrayBuffer) return new Uint8Array(data);
|
|
49
|
+
if (ArrayBuffer.isView(data)) {
|
|
50
|
+
return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
51
|
+
}
|
|
52
|
+
if (typeof Blob !== 'undefined' && data instanceof Blob) {
|
|
53
|
+
return new Uint8Array(await data.arrayBuffer());
|
|
54
|
+
}
|
|
55
|
+
throw ERRORS.TypedError(
|
|
56
|
+
HardwareErrorCode.CallMethodInvalidParameter,
|
|
57
|
+
'Unsupported FilesystemFileWrite data'
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function normalizeChunkSize(value: unknown, maxChunkSize: number): number {
|
|
62
|
+
const numeric = Number(value);
|
|
63
|
+
if (!Number.isFinite(numeric) || numeric <= 0) return maxChunkSize;
|
|
64
|
+
return Math.min(Math.max(Math.floor(numeric), MIN_FILE_CHUNK_SIZE), maxChunkSize);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function getDeviceTransferProgress(before: number, after: number, total: number) {
|
|
68
|
+
if (!Number.isFinite(total) || total <= 0) return 100;
|
|
69
|
+
if (before <= 0 && after < total) return 0;
|
|
70
|
+
if (after >= total) return 100;
|
|
71
|
+
return Math.min(Math.max(Math.ceil((after / total) * 100), 1), 99);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function getConfirmedProgress(processed: number, total: number, written: number, length: number) {
|
|
75
|
+
if (Number.isFinite(processed) && Number.isFinite(total) && total > 0) {
|
|
76
|
+
if (processed >= total) return 100;
|
|
77
|
+
return Math.min(Math.max(Math.floor((processed / total) * 100), 0), 99);
|
|
78
|
+
}
|
|
79
|
+
if (length > 0) return written >= length ? 100 : Math.floor((written / length) * 100);
|
|
80
|
+
return 100;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export async function writeProtocolV2File(options: ProtocolV2FileWriteOptions) {
|
|
84
|
+
options.throwIfAborted?.();
|
|
85
|
+
const data = await dataToUint8Array(options.data);
|
|
86
|
+
const dataLength = data.byteLength;
|
|
87
|
+
const startOffset =
|
|
88
|
+
Number.isFinite(options.offset) && Number(options.offset) > 0 ? Number(options.offset) : 0;
|
|
89
|
+
const totalSize =
|
|
90
|
+
Number.isFinite(options.totalSize) && Number(options.totalSize) > 0
|
|
91
|
+
? Number(options.totalSize)
|
|
92
|
+
: startOffset + dataLength;
|
|
93
|
+
|
|
94
|
+
if (totalSize < startOffset + dataLength) {
|
|
95
|
+
throw ERRORS.TypedError(
|
|
96
|
+
HardwareErrorCode.RuntimeError,
|
|
97
|
+
`FilesystemFileWrite totalSize ${totalSize} is smaller than offset + data length ${
|
|
98
|
+
startOffset + dataLength
|
|
99
|
+
}`
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const chunkSize = normalizeChunkSize(
|
|
104
|
+
options.chunkSize ?? options.chunkLen,
|
|
105
|
+
getProtocolV2FileChunkLimit()
|
|
106
|
+
);
|
|
107
|
+
let written = 0;
|
|
108
|
+
let chunks = 0;
|
|
109
|
+
let lastMessage: Record<string, unknown> | undefined;
|
|
110
|
+
const startTime = Date.now();
|
|
111
|
+
|
|
112
|
+
while (written < dataLength) {
|
|
113
|
+
options.throwIfAborted?.();
|
|
114
|
+
const chunk = data.slice(written, Math.min(written + chunkSize, dataLength));
|
|
115
|
+
const offset = startOffset + written;
|
|
116
|
+
const progress =
|
|
117
|
+
options.uiPercentage ??
|
|
118
|
+
getDeviceTransferProgress(offset, offset + chunk.byteLength, totalSize);
|
|
119
|
+
const response = await options.commands.typedCall(
|
|
120
|
+
'FilesystemFileWrite',
|
|
121
|
+
'FilesystemFile',
|
|
122
|
+
{
|
|
123
|
+
file: { path: options.path, offset, total_size: totalSize, data: chunk },
|
|
124
|
+
overwrite: chunks === 0 ? options.overwrite ?? false : false,
|
|
125
|
+
append: options.append ?? false,
|
|
126
|
+
ui_percentage: progress,
|
|
127
|
+
},
|
|
128
|
+
{ timeoutMs: options.timeoutMs }
|
|
129
|
+
);
|
|
130
|
+
options.throwIfAborted?.();
|
|
131
|
+
lastMessage = response.message;
|
|
132
|
+
const processedByte = Number(response.message?.processed_byte);
|
|
133
|
+
written =
|
|
134
|
+
Number.isFinite(processedByte) && processedByte > offset
|
|
135
|
+
? processedByte - startOffset
|
|
136
|
+
: written + chunk.byteLength;
|
|
137
|
+
if (written > dataLength) {
|
|
138
|
+
throw ERRORS.TypedError(
|
|
139
|
+
HardwareErrorCode.RuntimeError,
|
|
140
|
+
`FilesystemFileWrite invalid processed_byte ${processedByte}`
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
chunks += 1;
|
|
144
|
+
const elapsedMs = Date.now() - startTime;
|
|
145
|
+
const transferredBytes = Math.min(written, dataLength);
|
|
146
|
+
options.onProgress?.({
|
|
147
|
+
progress: getConfirmedProgress(startOffset + written, totalSize, written, dataLength),
|
|
148
|
+
transferredBytes,
|
|
149
|
+
totalBytes: dataLength,
|
|
150
|
+
rateBytesPerSecond:
|
|
151
|
+
elapsedMs > 0 ? Math.round((transferredBytes / elapsedMs) * 1000) : undefined,
|
|
152
|
+
elapsedMs,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return {
|
|
157
|
+
...lastMessage,
|
|
158
|
+
path: options.path,
|
|
159
|
+
offset: startOffset,
|
|
160
|
+
total_size: totalSize,
|
|
161
|
+
processed_byte: startOffset + written,
|
|
162
|
+
chunks,
|
|
163
|
+
};
|
|
164
|
+
}
|
package/src/api/index.ts
CHANGED
|
@@ -49,6 +49,7 @@ export { default as ping } from './protocol-v2/Ping';
|
|
|
49
49
|
export { default as deviceReboot } from './protocol-v2/DeviceReboot';
|
|
50
50
|
export { default as deviceInfoGet } from './protocol-v2/DeviceInfoGet';
|
|
51
51
|
export { default as deviceStatusGet } from './protocol-v2/DeviceStatusGet';
|
|
52
|
+
export { default as deviceGetOnboardingStatus } from './protocol-v2/DeviceGetOnboardingStatus';
|
|
52
53
|
export { default as deviceSessionGet } from './protocol-v2/DeviceSessionGet';
|
|
53
54
|
export { default as deviceFirmwareUpdate } from './protocol-v2/DeviceFirmwareUpdate';
|
|
54
55
|
export { default as deviceGetFirmwareUpdateStatus } from './protocol-v2/DeviceGetFirmwareUpdateStatus';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { BaseMethod } from '../BaseMethod';
|
|
2
|
+
|
|
3
|
+
export default class DeviceGetOnboardingStatus extends BaseMethod {
|
|
4
|
+
init() {
|
|
5
|
+
this.requireProtocolV2 = true;
|
|
6
|
+
this.skipForceUpdateCheck = true;
|
|
7
|
+
this.useDevicePassphraseState = false;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async run() {
|
|
11
|
+
const { message } = await this.device.commands.typedCall(
|
|
12
|
+
'DevGetOnboardingStatus',
|
|
13
|
+
'DevOnboardingStatus',
|
|
14
|
+
{}
|
|
15
|
+
);
|
|
16
|
+
return message;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
import { blake2s } from '@noble/hashes/blake2s';
|
|
2
2
|
import { bytesToHex } from '@noble/hashes/utils';
|
|
3
|
-
import {
|
|
4
|
-
PROTOCOL_V2_BLE_FILE_CHUNK_SIZE,
|
|
5
|
-
PROTOCOL_V2_WEBUSB_FILE_CHUNK_SIZE,
|
|
6
|
-
WallpaperTarget,
|
|
7
|
-
} from '@onekeyfe/hd-transport';
|
|
8
3
|
|
|
9
4
|
import { BaseMethod } from '../BaseMethod';
|
|
10
5
|
import { invalidParameter } from '../helpers/filesystemValidation';
|
|
11
|
-
import {
|
|
6
|
+
import { writeProtocolV2File } from '../helpers/protocolV2FileWrite';
|
|
12
7
|
import {
|
|
13
8
|
encodePro2Wallpaper,
|
|
14
9
|
PRO2_WALLPAPER_HEIGHT,
|
|
@@ -34,13 +29,6 @@ export type DeviceUploadWallpaperResponse = {
|
|
|
34
29
|
const WALLPAPER_DIRECTORY = 'vol0:/wallpapers/user';
|
|
35
30
|
const SAFE_FILE_NAME = /^[A-Za-z0-9_-]+(?:\.bin)?$/;
|
|
36
31
|
|
|
37
|
-
function getDefaultChunkSize(): number {
|
|
38
|
-
const env = DataManager.getSettings('env');
|
|
39
|
-
return env && DataManager.isBleConnect(env)
|
|
40
|
-
? PROTOCOL_V2_BLE_FILE_CHUNK_SIZE
|
|
41
|
-
: PROTOCOL_V2_WEBUSB_FILE_CHUNK_SIZE;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
32
|
function normalizeFileName(fileName: string | undefined, data: Uint8Array): string {
|
|
45
33
|
if (fileName !== undefined && (!fileName || !SAFE_FILE_NAME.test(fileName))) {
|
|
46
34
|
throw invalidParameter(
|
|
@@ -105,39 +93,16 @@ export default class DeviceUploadWallpaper extends BaseMethod<DeviceUploadWallpa
|
|
|
105
93
|
const encoded = this.encoded;
|
|
106
94
|
if (!encoded) throw invalidParameter('Wallpaper data has not been initialized.');
|
|
107
95
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
file: {
|
|
119
|
-
path: this.path,
|
|
120
|
-
offset,
|
|
121
|
-
total_size: encoded.data.byteLength,
|
|
122
|
-
data: chunk,
|
|
123
|
-
},
|
|
124
|
-
overwrite: offset === 0,
|
|
125
|
-
append: false,
|
|
126
|
-
ui_percentage: Math.min(
|
|
127
|
-
Math.ceil(((offset + chunk.byteLength) / encoded.data.byteLength) * 100),
|
|
128
|
-
100
|
|
129
|
-
),
|
|
130
|
-
},
|
|
131
|
-
{ timeoutMs: undefined }
|
|
132
|
-
);
|
|
133
|
-
const processedByte = Number(response.message?.processed_byte);
|
|
134
|
-
offset = Number.isFinite(processedByte) && processedByte > offset
|
|
135
|
-
? processedByte
|
|
136
|
-
: offset + chunk.byteLength;
|
|
137
|
-
if (offset > encoded.data.byteLength) {
|
|
138
|
-
throw invalidParameter(`Invalid processed_byte returned by device: ${processedByte}.`);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
96
|
+
await writeProtocolV2File({
|
|
97
|
+
commands: this.device.commands,
|
|
98
|
+
path: this.path,
|
|
99
|
+
data: encoded.data,
|
|
100
|
+
totalSize: encoded.data.byteLength,
|
|
101
|
+
chunkSize: this.params.chunkSize,
|
|
102
|
+
overwrite: true,
|
|
103
|
+
append: false,
|
|
104
|
+
throwIfAborted: () => this.throwIfAborted(),
|
|
105
|
+
});
|
|
141
106
|
this.uploaded = true;
|
|
142
107
|
}
|
|
143
108
|
|
|
@@ -146,9 +111,8 @@ export default class DeviceUploadWallpaper extends BaseMethod<DeviceUploadWallpa
|
|
|
146
111
|
if (!encoded) throw invalidParameter('Wallpaper data has not been initialized.');
|
|
147
112
|
await this.ensureDirectory();
|
|
148
113
|
await this.upload();
|
|
149
|
-
const response = await this.device.commands.typedCall('
|
|
150
|
-
|
|
151
|
-
path: this.path,
|
|
114
|
+
const response = await this.device.commands.typedCall('DeviceSettingsSet', 'Success', {
|
|
115
|
+
settings: { wallpaper_path: this.path },
|
|
152
116
|
});
|
|
153
117
|
return {
|
|
154
118
|
path: this.path,
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { EDeviceType, EFirmwareType } from '@onekeyfe/hd-shared';
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
|
|
3
|
+
import {
|
|
4
|
+
isProtocolV2BootloaderDeviceInfo,
|
|
5
|
+
isProtocolV2RomloaderDeviceInfo,
|
|
6
|
+
} from '../protocols/protocol-v2/features';
|
|
7
|
+
|
|
5
8
|
import type { DeviceFirmwareImageInfo, ProtocolV2DeviceInfo } from '@onekeyfe/hd-transport';
|
|
6
|
-
import {
|
|
9
|
+
import type { PROTO } from '../constants';
|
|
10
|
+
import type { DeviceFeaturesMode, Features } from '../types';
|
|
7
11
|
|
|
8
12
|
type ProtocolV1FeaturesCompat = PROTO.Features &
|
|
9
13
|
Partial<PROTO.OnekeyFeatures> & {
|
|
@@ -204,7 +208,7 @@ export const buildProtocolV1FeaturesPayload = (
|
|
|
204
208
|
},
|
|
205
209
|
sessionId,
|
|
206
210
|
raw: {
|
|
207
|
-
protocolV1Features
|
|
211
|
+
protocolV1Features,
|
|
208
212
|
},
|
|
209
213
|
};
|
|
210
214
|
};
|
|
@@ -223,7 +227,7 @@ export const buildProtocolV2FeaturesPayload = (
|
|
|
223
227
|
const info = deviceInfo;
|
|
224
228
|
const fwApplication = info?.fw?.application;
|
|
225
229
|
const fwBootloader = info?.fw?.bootloader;
|
|
226
|
-
const fwBoard =
|
|
230
|
+
const fwBoard = info?.fw?.romloader;
|
|
227
231
|
const bleApplication = info?.coprocessor?.application;
|
|
228
232
|
const status = info?.status;
|
|
229
233
|
|
|
@@ -249,14 +253,18 @@ export const buildProtocolV2FeaturesPayload = (
|
|
|
249
253
|
const unlocked = firstValue(status?.unlocked, previous?.unlocked) ?? null;
|
|
250
254
|
const attachToPinEnabled = status?.attach_to_pin_enabled ?? null;
|
|
251
255
|
const unlockedAttachPin = status?.unlocked_by_attach_to_pin ?? undefined;
|
|
256
|
+
const romloaderMode = isProtocolV2RomloaderDeviceInfo(info);
|
|
252
257
|
const bootloaderMode = isProtocolV2BootloaderDeviceInfo(info);
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
258
|
+
let mode: DeviceFeaturesMode = 'unknown';
|
|
259
|
+
if (romloaderMode) {
|
|
260
|
+
mode = 'romloader';
|
|
261
|
+
} else if (bootloaderMode) {
|
|
262
|
+
mode = 'bootloader';
|
|
263
|
+
} else if (initialized === false) {
|
|
264
|
+
mode = 'notInitialized';
|
|
265
|
+
} else if (initialized === true) {
|
|
266
|
+
mode = 'normal';
|
|
267
|
+
}
|
|
260
268
|
|
|
261
269
|
return {
|
|
262
270
|
protocol: 'V2',
|
|
@@ -13,6 +13,10 @@ import {
|
|
|
13
13
|
getDeviceUUID,
|
|
14
14
|
getFirmwareType,
|
|
15
15
|
} from '../utils/deviceInfoUtils';
|
|
16
|
+
import {
|
|
17
|
+
isProtocolV2BootloaderDeviceInfo,
|
|
18
|
+
isProtocolV2RomloaderDeviceInfo,
|
|
19
|
+
} from '../protocols/protocol-v2/features';
|
|
16
20
|
|
|
17
21
|
import type {
|
|
18
22
|
DeviceInfoProtocol,
|
|
@@ -26,7 +30,6 @@ import type {
|
|
|
26
30
|
} from '../types/api/getDeviceInfo';
|
|
27
31
|
import type { Features, OnekeyFeatures } from '../types';
|
|
28
32
|
import type { DeviceFirmwareImageInfo, ProtocolV2DeviceInfo } from '@onekeyfe/hd-transport';
|
|
29
|
-
import { isProtocolV2BootloaderDeviceInfo } from '../protocols/protocol-v2/features';
|
|
30
33
|
|
|
31
34
|
type BuildProtocolV1ProfileParams = {
|
|
32
35
|
protocol?: DeviceInfoProtocol;
|
|
@@ -87,6 +90,7 @@ const getDeviceMode = (features?: Features): DeviceInfoStatus['mode'] => {
|
|
|
87
90
|
};
|
|
88
91
|
|
|
89
92
|
const getProtocolV2Mode = (deviceInfo?: ProtocolV2DeviceInfo): DeviceInfoStatus['mode'] => {
|
|
93
|
+
if (isProtocolV2RomloaderDeviceInfo(deviceInfo)) return 'romloader';
|
|
90
94
|
if (isProtocolV2BootloaderDeviceInfo(deviceInfo)) return 'bootloader';
|
|
91
95
|
const initialized = deviceInfo?.status?.init_states;
|
|
92
96
|
if (initialized === false) return 'notInitialized';
|
|
@@ -154,9 +158,7 @@ const normalizeV2Versions = (deviceInfo?: ProtocolV2DeviceInfo): DeviceProfileVe
|
|
|
154
158
|
return {
|
|
155
159
|
firmware: firstMeaningfulVersion(getImageVersion(info?.fw?.application)),
|
|
156
160
|
bootloader: firstMeaningfulVersion(getImageVersion(info?.fw?.bootloader)),
|
|
157
|
-
board: firstMeaningfulVersion(
|
|
158
|
-
getImageVersion(info?.fw?.application_data ?? info?.fw?.romloader)
|
|
159
|
-
),
|
|
161
|
+
board: firstMeaningfulVersion(getImageVersion(info?.fw?.romloader)),
|
|
160
162
|
ble: firstMeaningfulVersion(getImageVersion(info?.coprocessor?.application)),
|
|
161
163
|
se01: firstMeaningfulVersion(getImageVersion(info?.se1?.application)),
|
|
162
164
|
se02: firstMeaningfulVersion(getImageVersion(info?.se2?.application)),
|
|
@@ -245,8 +247,8 @@ const normalizeV2Verify = (deviceInfo?: ProtocolV2DeviceInfo): DeviceProfileVeri
|
|
|
245
247
|
firmwareHash: getImageHash(info?.fw?.application),
|
|
246
248
|
bootloaderBuildId: getImageBuildId(info?.fw?.bootloader),
|
|
247
249
|
bootloaderHash: getImageHash(info?.fw?.bootloader),
|
|
248
|
-
boardBuildId: getImageBuildId(info?.fw?.
|
|
249
|
-
boardHash: getImageHash(info?.fw?.
|
|
250
|
+
boardBuildId: getImageBuildId(info?.fw?.romloader),
|
|
251
|
+
boardHash: getImageHash(info?.fw?.romloader),
|
|
250
252
|
bleBuildId: getImageBuildId(info?.coprocessor?.application),
|
|
251
253
|
bleHash: getImageHash(info?.coprocessor?.application),
|
|
252
254
|
se01BuildId: getImageBuildId(info?.se1?.application),
|
package/src/inject.ts
CHANGED
|
@@ -162,6 +162,8 @@ export const createCoreApi = (
|
|
|
162
162
|
deviceReboot: (connectId, params) => call({ ...params, connectId, method: 'deviceReboot' }),
|
|
163
163
|
deviceInfoGet: (connectId, params) => call({ ...params, connectId, method: 'deviceInfoGet' }),
|
|
164
164
|
deviceStatusGet: (connectId, params) => call({ ...params, connectId, method: 'deviceStatusGet' }),
|
|
165
|
+
deviceGetOnboardingStatus: (connectId, params) =>
|
|
166
|
+
call({ ...params, connectId, method: 'deviceGetOnboardingStatus' }),
|
|
165
167
|
deviceSessionGet: (connectId, params) =>
|
|
166
168
|
call({ ...params, connectId, method: 'deviceSessionGet' }),
|
|
167
169
|
deviceFirmwareUpdate: (connectId, params) =>
|
|
@@ -50,8 +50,26 @@ export const getProtocolV2SeState = (se?: DeviceSEInfo): ProtocolV2SeStateLabel
|
|
|
50
50
|
export const getProtocolV2SeType = (se?: DeviceSEInfo): string | null =>
|
|
51
51
|
normalizeEnumValue(DeviceSeType, se?.type);
|
|
52
52
|
|
|
53
|
+
/**
|
|
54
|
+
* 兼容尚未提供显式 runtime mode 的 Protocol V2 固件。
|
|
55
|
+
*
|
|
56
|
+
* 当前 romloader 只上报 hw、fw.romloader 和 fw.bootloader;bootloader
|
|
57
|
+
* 还会上报 application/application_data、coprocessor 或 SE 信息。
|
|
58
|
+
*/
|
|
59
|
+
export const isProtocolV2RomloaderDeviceInfo = (deviceInfo?: ProtocolV2DeviceInfo | null) =>
|
|
60
|
+
!!deviceInfo &&
|
|
61
|
+
deviceInfo.status == null &&
|
|
62
|
+
deviceInfo.fw?.romloader != null &&
|
|
63
|
+
deviceInfo.fw?.application == null &&
|
|
64
|
+
deviceInfo.fw?.application_data == null &&
|
|
65
|
+
deviceInfo.coprocessor == null &&
|
|
66
|
+
deviceInfo.se1 == null &&
|
|
67
|
+
deviceInfo.se2 == null &&
|
|
68
|
+
deviceInfo.se3 == null &&
|
|
69
|
+
deviceInfo.se4 == null;
|
|
70
|
+
|
|
53
71
|
export const isProtocolV2BootloaderDeviceInfo = (deviceInfo?: ProtocolV2DeviceInfo | null) =>
|
|
54
|
-
!!deviceInfo && deviceInfo.status == null;
|
|
72
|
+
!!deviceInfo && deviceInfo.status == null && !isProtocolV2RomloaderDeviceInfo(deviceInfo);
|
|
55
73
|
|
|
56
74
|
export const PROTOCOL_V2_FEATURES_DEVICE_INFO_REQUEST = {
|
|
57
75
|
targets: {
|
|
@@ -4,6 +4,8 @@ export {
|
|
|
4
4
|
PROTOCOL_V2_FEATURES_DEVICE_INFO_REQUEST,
|
|
5
5
|
PROTOCOL_V2_STATUS_DEVICE_INFO_REQUEST,
|
|
6
6
|
PROTOCOL_V2_VERSIONS_DEVICE_INFO_REQUEST,
|
|
7
|
+
isProtocolV2BootloaderDeviceInfo,
|
|
8
|
+
isProtocolV2RomloaderDeviceInfo,
|
|
7
9
|
getProtocolV2SeState,
|
|
8
10
|
getProtocolV2SeType,
|
|
9
11
|
} from './features';
|
|
@@ -16,7 +16,7 @@ export type GetDeviceInfoParams = {
|
|
|
16
16
|
includeRaw?: boolean;
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
export type DeviceInfoMode = 'normal' | 'bootloader' | 'notInitialized' | 'unknown';
|
|
19
|
+
export type DeviceInfoMode = 'normal' | 'bootloader' | 'romloader' | 'notInitialized' | 'unknown';
|
|
20
20
|
|
|
21
21
|
export type DeviceInfoStatus = {
|
|
22
22
|
mode: DeviceInfoMode;
|
package/src/types/api/index.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
deviceFactoryInfoSet,
|
|
4
4
|
deviceFirmwareUpdate,
|
|
5
5
|
deviceGetFirmwareUpdateStatus,
|
|
6
|
+
deviceGetOnboardingStatus,
|
|
6
7
|
deviceInfoGet,
|
|
7
8
|
deviceReboot,
|
|
8
9
|
deviceSessionGet,
|
|
@@ -266,6 +267,7 @@ export type CoreApi = {
|
|
|
266
267
|
deviceReboot: typeof deviceReboot;
|
|
267
268
|
deviceInfoGet: typeof deviceInfoGet;
|
|
268
269
|
deviceStatusGet: typeof deviceStatusGet;
|
|
270
|
+
deviceGetOnboardingStatus: typeof deviceGetOnboardingStatus;
|
|
269
271
|
deviceSessionGet: typeof deviceSessionGet;
|
|
270
272
|
deviceFirmwareUpdate: typeof deviceFirmwareUpdate;
|
|
271
273
|
deviceGetFirmwareUpdateStatus: typeof deviceGetFirmwareUpdateStatus;
|
|
@@ -2,6 +2,7 @@ import type { CommonParams, Response } from '../params';
|
|
|
2
2
|
import type {
|
|
3
3
|
DeviceFactoryInfo,
|
|
4
4
|
DeviceFirmwareUpdateStatus,
|
|
5
|
+
DevOnboardingStatus,
|
|
5
6
|
DeviceSession,
|
|
6
7
|
DeviceSettings,
|
|
7
8
|
DeviceStatus,
|
|
@@ -111,6 +112,11 @@ export declare function deviceStatusGet(
|
|
|
111
112
|
params?: CommonParams
|
|
112
113
|
): Response<DeviceStatus>;
|
|
113
114
|
|
|
115
|
+
export declare function deviceGetOnboardingStatus(
|
|
116
|
+
connectId: string,
|
|
117
|
+
params?: CommonParams
|
|
118
|
+
): Response<DevOnboardingStatus>;
|
|
119
|
+
|
|
114
120
|
export declare function deviceSessionGet(
|
|
115
121
|
connectId: string,
|
|
116
122
|
params?: CommonParams
|