@onekeyfe/hd-core 1.2.8-alpha.17 → 1.2.8-alpha.19
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__/usb-identity-probe.test.ts +102 -1
- package/dist/api/SearchDevices.d.ts.map +1 -1
- package/dist/index.js +37 -8
- package/package.json +4 -4
- package/src/api/SearchDevices.ts +47 -13
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DeviceType } from '@onekeyfe/hd-transport';
|
|
1
|
+
import protocolTransport, { DeviceType } from '@onekeyfe/hd-transport';
|
|
2
2
|
import { EDeviceType } from '@onekeyfe/hd-shared';
|
|
3
3
|
|
|
4
4
|
import {
|
|
@@ -148,6 +148,41 @@ describe('isolated USB identity probe', () => {
|
|
|
148
148
|
);
|
|
149
149
|
});
|
|
150
150
|
|
|
151
|
+
test.each([
|
|
152
|
+
{ onekey_device_type: 'CLASSIC', major_version: 2, minor_version: 8, patch_version: 0 },
|
|
153
|
+
{ onekey_device_type: 'TOUCH', major_version: 4, minor_version: 4, patch_version: 0 },
|
|
154
|
+
])(
|
|
155
|
+
'preserves GetFeatures identity when the legacy V1 schema has no vendor query (%s)',
|
|
156
|
+
async firmware => {
|
|
157
|
+
const transport = createTransport();
|
|
158
|
+
let messages = protocolTransport.parseConfigure(
|
|
159
|
+
JSON.stringify(DataManager.getProtobufMessages())
|
|
160
|
+
);
|
|
161
|
+
transport.configure.mockImplementation((schema: string) => {
|
|
162
|
+
messages = protocolTransport.parseConfigure(schema);
|
|
163
|
+
});
|
|
164
|
+
transport.call.mockImplementation((_session, name, data) => {
|
|
165
|
+
protocolTransport.ProtocolV1.encodeMessageChunks(messages, name, data);
|
|
166
|
+
return Promise.resolve({
|
|
167
|
+
type: 'Features',
|
|
168
|
+
message: { ...firmware, device_id: 'LEGACY_WALLET_ID' },
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
await expect(
|
|
172
|
+
probeUsbDeviceIdentitiesWithTransport(transport, 'webusb')
|
|
173
|
+
).resolves.toMatchObject([
|
|
174
|
+
{
|
|
175
|
+
path: descriptor.path,
|
|
176
|
+
serialNo: null,
|
|
177
|
+
deviceId: 'LEGACY_WALLET_ID',
|
|
178
|
+
connectProtocol: 'V1',
|
|
179
|
+
},
|
|
180
|
+
]);
|
|
181
|
+
expect(transport.call.mock.calls.map(call => call[1])).toEqual(['GetFeatures']);
|
|
182
|
+
expect(transport.release).toHaveBeenCalledWith('usb-transport-handle', false);
|
|
183
|
+
}
|
|
184
|
+
);
|
|
185
|
+
|
|
151
186
|
test('does not substitute a USB path for a missing business identity', async () => {
|
|
152
187
|
const transport = createTransport();
|
|
153
188
|
transport.call
|
|
@@ -171,6 +206,72 @@ describe('isolated USB identity probe', () => {
|
|
|
171
206
|
expect(transport.release).not.toHaveBeenCalled();
|
|
172
207
|
});
|
|
173
208
|
|
|
209
|
+
test('retries its own failed Bridge release before probing again', async () => {
|
|
210
|
+
const transport = createTransport();
|
|
211
|
+
let held: string | undefined;
|
|
212
|
+
transport.enumerate.mockImplementation(() =>
|
|
213
|
+
Promise.resolve([{ ...descriptor, commType: 'bridge', session: held }])
|
|
214
|
+
);
|
|
215
|
+
transport.acquire.mockImplementation(() => {
|
|
216
|
+
held = 'probe-transport-handle';
|
|
217
|
+
return Promise.resolve(held);
|
|
218
|
+
});
|
|
219
|
+
transport.release
|
|
220
|
+
.mockRejectedValueOnce(new Error('release request lost'))
|
|
221
|
+
.mockRejectedValueOnce(new Error('Bridge still unavailable'))
|
|
222
|
+
.mockImplementation(() => {
|
|
223
|
+
held = undefined;
|
|
224
|
+
return Promise.resolve(undefined);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
await expect(probeUsbDeviceIdentitiesWithTransport(transport, 'bridge')).resolves.toEqual([]);
|
|
228
|
+
await expect(probeUsbDeviceIdentitiesWithTransport(transport, 'bridge')).resolves.toEqual([]);
|
|
229
|
+
expect(transport.acquire).toHaveBeenCalledTimes(1);
|
|
230
|
+
expect(transport.call).toHaveBeenCalledTimes(1);
|
|
231
|
+
await expect(probeUsbDeviceIdentitiesWithTransport(transport, 'bridge')).resolves.toHaveLength(
|
|
232
|
+
1
|
|
233
|
+
);
|
|
234
|
+
expect(transport.acquire).toHaveBeenCalledTimes(2);
|
|
235
|
+
expect(transport.release).toHaveBeenCalledTimes(4);
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
test.each([undefined, 'foreign-transport-handle'])(
|
|
239
|
+
'does not retry a stale Bridge release when ownership changes to %s',
|
|
240
|
+
async replacement => {
|
|
241
|
+
const transport = createTransport();
|
|
242
|
+
transport.enumerate.mockResolvedValue([{ ...descriptor, commType: 'bridge' }]);
|
|
243
|
+
transport.release.mockRejectedValueOnce(new Error('release response lost'));
|
|
244
|
+
await probeUsbDeviceIdentitiesWithTransport(transport, 'bridge');
|
|
245
|
+
transport.enumerate.mockResolvedValue([
|
|
246
|
+
{ ...descriptor, commType: 'bridge', session: replacement },
|
|
247
|
+
]);
|
|
248
|
+
transport.release.mockClear();
|
|
249
|
+
const result = await probeUsbDeviceIdentitiesWithTransport(transport, 'bridge');
|
|
250
|
+
expect(result).toHaveLength(replacement ? 0 : 1);
|
|
251
|
+
expect(transport.release).toHaveBeenCalledTimes(replacement ? 0 : 1);
|
|
252
|
+
if (replacement) {
|
|
253
|
+
transport.enumerate.mockResolvedValue([{ ...descriptor, commType: 'bridge' }]);
|
|
254
|
+
await expect(
|
|
255
|
+
probeUsbDeviceIdentitiesWithTransport(transport, 'bridge')
|
|
256
|
+
).resolves.toHaveLength(1);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
);
|
|
260
|
+
|
|
261
|
+
test('never cleans up a Bridge handle recorded by another transport instance', async () => {
|
|
262
|
+
const transport = createTransport();
|
|
263
|
+
transport.enumerate.mockResolvedValue([{ ...descriptor, commType: 'bridge' }]);
|
|
264
|
+
transport.release.mockRejectedValueOnce(new Error('release request lost'));
|
|
265
|
+
await probeUsbDeviceIdentitiesWithTransport(transport, 'bridge');
|
|
266
|
+
const other = createTransport();
|
|
267
|
+
other.enumerate.mockResolvedValue([
|
|
268
|
+
{ ...descriptor, commType: 'bridge', session: 'usb-transport-handle' },
|
|
269
|
+
]);
|
|
270
|
+
await expect(probeUsbDeviceIdentitiesWithTransport(other, 'bridge')).resolves.toEqual([]);
|
|
271
|
+
expect(other.release).not.toHaveBeenCalled();
|
|
272
|
+
expect(other.acquire).not.toHaveBeenCalled();
|
|
273
|
+
});
|
|
274
|
+
|
|
174
275
|
test('reuses identity only for the exact active WebUSB handle', () => {
|
|
175
276
|
const handle = {};
|
|
176
277
|
const endpoint = { ...descriptor, device: handle };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchDevices.d.ts","sourceRoot":"","sources":["../../src/api/SearchDevices.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAU1C,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEvE,OAAO,KAAK,eAAe,MAAM,2BAA2B,CAAC;AAC7D,OAAO,KAAK,EACV,YAAY,EACZ,gBAAgB,IAAI,gBAAgB,EAEpC,SAAS,EACV,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAI/C,KAAK,kBAAkB,GAAG;IACxB,4BAA4B,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;IAC9D,OAAO,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK;QAAE,MAAM,EAAE;YAAE,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,GAAG,SAAS,CAAC;CAC7E,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG,IAAI,CAAC,gBAAgB,EAAE,MAAM,GAAG,UAAU,CAAC,GAClF,OAAO,CAAC,IAAI,CAAC,gBAAgB,EAAE,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC;AA4CpD,eAAO,MAAM,yBAAyB,eACxB,0BAA0B,gBACxB,kBAAkB,KAC/B,iBAAiB,GAAG,SAYtB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG,IAAI,CAC1C,SAAS,EACT,SAAS,GAAG,MAAM,GAAG,iBAAiB,GAAG,qBAAqB,CAC/D,GAAG;IACF,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IAClC,SAAS,EAAE,MAAM,OAAO,CAAC,0BAA0B,EAAE,CAAC,CAAC;IACvD,OAAO,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAC9D,SAAS,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzD,CAAC;
|
|
1
|
+
{"version":3,"file":"SearchDevices.d.ts","sourceRoot":"","sources":["../../src/api/SearchDevices.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAU1C,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEvE,OAAO,KAAK,eAAe,MAAM,2BAA2B,CAAC;AAC7D,OAAO,KAAK,EACV,YAAY,EACZ,gBAAgB,IAAI,gBAAgB,EAEpC,SAAS,EACV,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAI/C,KAAK,kBAAkB,GAAG;IACxB,4BAA4B,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;IAC9D,OAAO,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK;QAAE,MAAM,EAAE;YAAE,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,GAAG,SAAS,CAAC;CAC7E,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG,IAAI,CAAC,gBAAgB,EAAE,MAAM,GAAG,UAAU,CAAC,GAClF,OAAO,CAAC,IAAI,CAAC,gBAAgB,EAAE,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC;AA4CpD,eAAO,MAAM,yBAAyB,eACxB,0BAA0B,gBACxB,kBAAkB,KAC/B,iBAAiB,GAAG,SAYtB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG,IAAI,CAC1C,SAAS,EACT,SAAS,GAAG,MAAM,GAAG,iBAAiB,GAAG,qBAAqB,CAC/D,GAAG;IACF,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IAClC,SAAS,EAAE,MAAM,OAAO,CAAC,0BAA0B,EAAE,CAAC,CAAC;IACvD,OAAO,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAC9D,SAAS,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzD,CAAC;AAcF,eAAO,MAAM,qCAAqC,cACrC,yBAAyB,YAC1B,iBAAiB,CAAC,UAAU,CAAC,mCACP,0BAA0B,KAAK,iBAAiB,GAAG,SAAS,kBAC3F,QAAQ,iBAAiB,EAAE,CAgI7B,CAAC;AAsBF,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,UAAU;IACnD,SAAS,CAAC,EAAE,eAAe,CAAa;IAExC,IAAI;IAME,GAAG,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;CAuFrC"}
|
package/dist/index.js
CHANGED
|
@@ -47231,6 +47231,7 @@ const identityProbeLogger = {
|
|
|
47231
47231
|
warn: () => undefined,
|
|
47232
47232
|
error: () => undefined,
|
|
47233
47233
|
};
|
|
47234
|
+
const pendingBridgeProbeReleases = new WeakMap();
|
|
47234
47235
|
const probeUsbDeviceIdentitiesWithTransport = (transport, commType, getOwnedIdentity) => __awaiter(void 0, void 0, void 0, function* () {
|
|
47235
47236
|
var _a;
|
|
47236
47237
|
yield transport.init(identityProbeLogger);
|
|
@@ -47238,6 +47239,14 @@ const probeUsbDeviceIdentitiesWithTransport = (transport, commType, getOwnedIden
|
|
|
47238
47239
|
yield transport.configure(defaultMessages);
|
|
47239
47240
|
yield ((_a = transport.configureProtocolV2) === null || _a === void 0 ? void 0 : _a.call(transport, JSON.stringify(DataManager.getProtobufMessages('v2Schema'))));
|
|
47240
47241
|
const descriptors = yield transport.enumerate();
|
|
47242
|
+
let pendingReleases = pendingBridgeProbeReleases.get(transport);
|
|
47243
|
+
if (commType === 'bridge' && pendingReleases) {
|
|
47244
|
+
for (const [path, session] of pendingReleases) {
|
|
47245
|
+
if (!descriptors.some(descriptor => descriptor.path === path && descriptor.session === session)) {
|
|
47246
|
+
pendingReleases.delete(path);
|
|
47247
|
+
}
|
|
47248
|
+
}
|
|
47249
|
+
}
|
|
47241
47250
|
const identities = [];
|
|
47242
47251
|
const readIdentity = (descriptor) => __awaiter(void 0, void 0, void 0, function* () {
|
|
47243
47252
|
var _b, _c;
|
|
@@ -47246,6 +47255,17 @@ const probeUsbDeviceIdentitiesWithTransport = (transport, commType, getOwnedIden
|
|
|
47246
47255
|
return undefined;
|
|
47247
47256
|
if (descriptors.filter(candidate => candidate.path === path).length !== 1)
|
|
47248
47257
|
return undefined;
|
|
47258
|
+
const pendingSession = commType === 'bridge' ? pendingReleases === null || pendingReleases === void 0 ? void 0 : pendingReleases.get(path) : undefined;
|
|
47259
|
+
if (pendingSession && descriptor.session === pendingSession) {
|
|
47260
|
+
try {
|
|
47261
|
+
yield transport.release(pendingSession, false);
|
|
47262
|
+
pendingReleases === null || pendingReleases === void 0 ? void 0 : pendingReleases.delete(path);
|
|
47263
|
+
descriptor = Object.assign(Object.assign({}, descriptor), { session: undefined });
|
|
47264
|
+
}
|
|
47265
|
+
catch (_d) {
|
|
47266
|
+
return undefined;
|
|
47267
|
+
}
|
|
47268
|
+
}
|
|
47249
47269
|
const owner = getOwnedIdentity === null || getOwnedIdentity === void 0 ? void 0 : getOwnedIdentity(descriptor);
|
|
47250
47270
|
if (owner) {
|
|
47251
47271
|
return owner;
|
|
@@ -47266,12 +47286,14 @@ const probeUsbDeviceIdentitiesWithTransport = (transport, commType, getOwnedIden
|
|
|
47266
47286
|
return undefined;
|
|
47267
47287
|
let features = buildProtocolV1FeaturesPayload(response.message);
|
|
47268
47288
|
if (!features.serialNo) {
|
|
47269
|
-
const { messages } = getSupportProtocolV1MessageSchema(features);
|
|
47270
|
-
if (
|
|
47271
|
-
|
|
47272
|
-
|
|
47273
|
-
|
|
47274
|
-
|
|
47289
|
+
const { messages, protocolV1MessageSchema } = getSupportProtocolV1MessageSchema(features);
|
|
47290
|
+
if (protocolV1MessageSchema === 'v1CurrentSchema') {
|
|
47291
|
+
if (messages)
|
|
47292
|
+
yield transport.configure(JSON.stringify(messages));
|
|
47293
|
+
const vendor = yield transport.call(session, 'OnekeyGetFeatures', {}, { timeoutMs: 3000 });
|
|
47294
|
+
if (vendor.type === 'OnekeyFeatures') {
|
|
47295
|
+
features = buildProtocolV1FeaturesPayload(Object.assign(Object.assign({}, response.message), vendor.message));
|
|
47296
|
+
}
|
|
47275
47297
|
}
|
|
47276
47298
|
}
|
|
47277
47299
|
identified = {
|
|
@@ -47298,15 +47320,22 @@ const probeUsbDeviceIdentitiesWithTransport = (transport, commType, getOwnedIden
|
|
|
47298
47320
|
};
|
|
47299
47321
|
}
|
|
47300
47322
|
}
|
|
47301
|
-
catch (
|
|
47323
|
+
catch (_e) {
|
|
47302
47324
|
}
|
|
47303
47325
|
finally {
|
|
47304
47326
|
if (session) {
|
|
47305
47327
|
try {
|
|
47306
47328
|
yield transport.release(session, false);
|
|
47307
47329
|
}
|
|
47308
|
-
catch (
|
|
47330
|
+
catch (_f) {
|
|
47309
47331
|
identified = undefined;
|
|
47332
|
+
if (commType === 'bridge') {
|
|
47333
|
+
if (!pendingReleases) {
|
|
47334
|
+
pendingReleases = new Map();
|
|
47335
|
+
pendingBridgeProbeReleases.set(transport, pendingReleases);
|
|
47336
|
+
}
|
|
47337
|
+
pendingReleases.set(path, session);
|
|
47338
|
+
}
|
|
47310
47339
|
}
|
|
47311
47340
|
}
|
|
47312
47341
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/hd-core",
|
|
3
|
-
"version": "1.2.8-alpha.
|
|
3
|
+
"version": "1.2.8-alpha.19",
|
|
4
4
|
"description": "Core processes and APIs for communicating with OneKey hardware devices.",
|
|
5
5
|
"author": "OneKey",
|
|
6
6
|
"homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"url": "https://github.com/OneKeyHQ/hardware-js-sdk/issues"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@onekeyfe/hd-shared": "1.2.8-alpha.
|
|
29
|
-
"@onekeyfe/hd-transport": "1.2.8-alpha.
|
|
28
|
+
"@onekeyfe/hd-shared": "1.2.8-alpha.19",
|
|
29
|
+
"@onekeyfe/hd-transport": "1.2.8-alpha.19",
|
|
30
30
|
"axios": "1.15.2",
|
|
31
31
|
"bignumber.js": "^9.0.2",
|
|
32
32
|
"buffer": "^6.0.3",
|
|
@@ -46,5 +46,5 @@
|
|
|
46
46
|
"@types/w3c-web-usb": "^1.0.10",
|
|
47
47
|
"@types/web-bluetooth": "^0.0.21"
|
|
48
48
|
},
|
|
49
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "822e744bceb68a0928ad89d445b985897432edcf"
|
|
50
50
|
}
|
package/src/api/SearchDevices.ts
CHANGED
|
@@ -109,6 +109,8 @@ const identityProbeLogger = {
|
|
|
109
109
|
error: () => undefined,
|
|
110
110
|
};
|
|
111
111
|
|
|
112
|
+
const pendingBridgeProbeReleases = new WeakMap<UsbIdentityProbeTransport, Map<string, string>>();
|
|
113
|
+
|
|
112
114
|
/** Runs on a separate transport; never initializes or switches the current Core. */
|
|
113
115
|
export const probeUsbDeviceIdentitiesWithTransport = async (
|
|
114
116
|
transport: UsbIdentityProbeTransport,
|
|
@@ -122,6 +124,16 @@ export const probeUsbDeviceIdentitiesWithTransport = async (
|
|
|
122
124
|
JSON.stringify(DataManager.getProtobufMessages('v2Schema'))
|
|
123
125
|
);
|
|
124
126
|
const descriptors = await transport.enumerate();
|
|
127
|
+
let pendingReleases = pendingBridgeProbeReleases.get(transport);
|
|
128
|
+
if (commType === 'bridge' && pendingReleases) {
|
|
129
|
+
for (const [path, session] of pendingReleases) {
|
|
130
|
+
if (
|
|
131
|
+
!descriptors.some(descriptor => descriptor.path === path && descriptor.session === session)
|
|
132
|
+
) {
|
|
133
|
+
pendingReleases.delete(path);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
125
137
|
const identities: UsbDeviceIdentity[] = [];
|
|
126
138
|
const readIdentity = async (
|
|
127
139
|
descriptor: UsbIdentityProbeDescriptor
|
|
@@ -129,6 +141,16 @@ export const probeUsbDeviceIdentitiesWithTransport = async (
|
|
|
129
141
|
const { path } = descriptor;
|
|
130
142
|
if (!path || descriptor.commType !== commType) return undefined;
|
|
131
143
|
if (descriptors.filter(candidate => candidate.path === path).length !== 1) return undefined;
|
|
144
|
+
const pendingSession = commType === 'bridge' ? pendingReleases?.get(path) : undefined;
|
|
145
|
+
if (pendingSession && descriptor.session === pendingSession) {
|
|
146
|
+
try {
|
|
147
|
+
await transport.release(pendingSession, false);
|
|
148
|
+
pendingReleases?.delete(path);
|
|
149
|
+
descriptor = { ...descriptor, session: undefined };
|
|
150
|
+
} catch {
|
|
151
|
+
return undefined;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
132
154
|
const owner = getOwnedIdentity?.(descriptor);
|
|
133
155
|
if (owner) {
|
|
134
156
|
return owner;
|
|
@@ -149,19 +171,22 @@ export const probeUsbDeviceIdentitiesWithTransport = async (
|
|
|
149
171
|
if (response.type !== 'Features') return undefined;
|
|
150
172
|
let features = buildProtocolV1FeaturesPayload(response.message as PROTO.Features);
|
|
151
173
|
if (!features.serialNo) {
|
|
152
|
-
const { messages } = getSupportProtocolV1MessageSchema(features);
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
174
|
+
const { messages, protocolV1MessageSchema } = getSupportProtocolV1MessageSchema(features);
|
|
175
|
+
// Legacy V1 has no OnekeyGetFeatures; keep the identity confirmed by GetFeatures.
|
|
176
|
+
if (protocolV1MessageSchema === 'v1CurrentSchema') {
|
|
177
|
+
if (messages) await transport.configure(JSON.stringify(messages));
|
|
178
|
+
const vendor = await transport.call(
|
|
179
|
+
session,
|
|
180
|
+
'OnekeyGetFeatures',
|
|
181
|
+
{},
|
|
182
|
+
{ timeoutMs: 3000 }
|
|
183
|
+
);
|
|
184
|
+
if (vendor.type === 'OnekeyFeatures') {
|
|
185
|
+
features = buildProtocolV1FeaturesPayload({
|
|
186
|
+
...response.message,
|
|
187
|
+
...vendor.message,
|
|
188
|
+
} as PROTO.Features);
|
|
189
|
+
}
|
|
165
190
|
}
|
|
166
191
|
}
|
|
167
192
|
identified = {
|
|
@@ -200,6 +225,15 @@ export const probeUsbDeviceIdentitiesWithTransport = async (
|
|
|
200
225
|
await transport.release(session, false);
|
|
201
226
|
} catch {
|
|
202
227
|
identified = undefined;
|
|
228
|
+
// Retain only our own Bridge handle; enumeration must confirm ownership
|
|
229
|
+
// before a later probe retries a release whose HTTP request may be lost.
|
|
230
|
+
if (commType === 'bridge') {
|
|
231
|
+
if (!pendingReleases) {
|
|
232
|
+
pendingReleases = new Map();
|
|
233
|
+
pendingBridgeProbeReleases.set(transport, pendingReleases);
|
|
234
|
+
}
|
|
235
|
+
pendingReleases.set(path, session);
|
|
236
|
+
}
|
|
203
237
|
}
|
|
204
238
|
}
|
|
205
239
|
}
|