@onekeyfe/hd-transport-web-device 1.0.34-alpha.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/dist/index.js ADDED
@@ -0,0 +1,766 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var transport = require('@onekeyfe/hd-transport');
6
+ var hdShared = require('@onekeyfe/hd-shared');
7
+ var ByteBuffer = require('bytebuffer');
8
+
9
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
10
+
11
+ var transport__default = /*#__PURE__*/_interopDefaultLegacy(transport);
12
+ var ByteBuffer__default = /*#__PURE__*/_interopDefaultLegacy(ByteBuffer);
13
+
14
+ /******************************************************************************
15
+ Copyright (c) Microsoft Corporation.
16
+
17
+ Permission to use, copy, modify, and/or distribute this software for any
18
+ purpose with or without fee is hereby granted.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
21
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
22
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
23
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
24
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
25
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
26
+ PERFORMANCE OF THIS SOFTWARE.
27
+ ***************************************************************************** */
28
+
29
+ function __awaiter(thisArg, _arguments, P, generator) {
30
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
31
+ return new (P || (P = Promise))(function (resolve, reject) {
32
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
33
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
34
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
35
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
36
+ });
37
+ }
38
+
39
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
40
+ var e = new Error(message);
41
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
42
+ };
43
+
44
+ const { parseConfigure: parseConfigure$1, buildEncodeBuffers, decodeProtocol, receiveOne: receiveOne$1, check: check$1 } = transport__default["default"];
45
+ const CONFIGURATION_ID = 1;
46
+ const INTERFACE_ID = 0;
47
+ const ENDPOINT_ID = 1;
48
+ const PACKET_SIZE = 64;
49
+ const HEADER_LENGTH = 6;
50
+ class WebUsbTransport {
51
+ constructor() {
52
+ this.name = 'WebUsbTransport';
53
+ this.stopped = false;
54
+ this.configured = false;
55
+ this.deviceList = [];
56
+ this.configurationId = CONFIGURATION_ID;
57
+ this.endpointId = ENDPOINT_ID;
58
+ this.interfaceId = INTERFACE_ID;
59
+ }
60
+ init(logger) {
61
+ this.Log = logger;
62
+ const { usb } = navigator;
63
+ if (!usb) {
64
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'WebUSB is not supported by current browsers');
65
+ }
66
+ this.usb = usb;
67
+ }
68
+ configure(signedData) {
69
+ const messages = parseConfigure$1(signedData);
70
+ this.configured = true;
71
+ this.messages = messages;
72
+ }
73
+ promptDeviceAccess() {
74
+ return __awaiter(this, void 0, void 0, function* () {
75
+ if (!this.usb)
76
+ return null;
77
+ try {
78
+ const device = yield this.usb.requestDevice({ filters: hdShared.ONEKEY_WEBUSB_FILTER });
79
+ return device;
80
+ }
81
+ catch (e) {
82
+ this.Log.debug('requestDevice error: ', e);
83
+ return null;
84
+ }
85
+ });
86
+ }
87
+ enumerate() {
88
+ return __awaiter(this, void 0, void 0, function* () {
89
+ yield this.getConnectedDevices();
90
+ return this.deviceList;
91
+ });
92
+ }
93
+ getConnectedDevices() {
94
+ return __awaiter(this, void 0, void 0, function* () {
95
+ if (!this.usb)
96
+ return [];
97
+ const devices = yield this.usb.getDevices();
98
+ const onekeyDevices = devices.filter(dev => {
99
+ const isOneKey = hdShared.ONEKEY_WEBUSB_FILTER.some(desc => dev.vendorId === desc.vendorId && dev.productId === desc.productId);
100
+ const hasSerialNumber = typeof dev.serialNumber === 'string' && dev.serialNumber.length > 0;
101
+ return isOneKey && hasSerialNumber;
102
+ });
103
+ this.deviceList = onekeyDevices.map(device => ({
104
+ path: device.serialNumber,
105
+ device,
106
+ }));
107
+ return this.deviceList;
108
+ });
109
+ }
110
+ acquire(input) {
111
+ var _a;
112
+ return __awaiter(this, void 0, void 0, function* () {
113
+ if (!input.path)
114
+ return;
115
+ try {
116
+ yield this.connect((_a = input.path) !== null && _a !== void 0 ? _a : '', true);
117
+ return yield Promise.resolve(input.path);
118
+ }
119
+ catch (e) {
120
+ this.Log.debug('acquire error: ', e);
121
+ throw e;
122
+ }
123
+ });
124
+ }
125
+ findDevice(path) {
126
+ return __awaiter(this, void 0, void 0, function* () {
127
+ if (this.deviceList.length === 0) {
128
+ yield this.getConnectedDevices();
129
+ }
130
+ let device = this.deviceList.find(d => d.path === path);
131
+ if (device == null) {
132
+ yield this.getConnectedDevices();
133
+ device = this.deviceList.find(d => d.path === path);
134
+ if (device == null) {
135
+ throw new Error('Action was interrupted.');
136
+ }
137
+ }
138
+ return device.device;
139
+ });
140
+ }
141
+ connect(path, first) {
142
+ return __awaiter(this, void 0, void 0, function* () {
143
+ const maxRetries = 5;
144
+ for (let i = 0; i < maxRetries; i++) {
145
+ try {
146
+ return yield this.connectToDevice(path, first);
147
+ }
148
+ catch (e) {
149
+ if (i === maxRetries - 1) {
150
+ throw e;
151
+ }
152
+ yield hdShared.wait(i * 200);
153
+ }
154
+ }
155
+ });
156
+ }
157
+ connectToDevice(path, first) {
158
+ return __awaiter(this, void 0, void 0, function* () {
159
+ const device = yield this.findDevice(path);
160
+ yield device.open();
161
+ if (first) {
162
+ yield device.selectConfiguration(this.configurationId);
163
+ try {
164
+ yield device.reset();
165
+ }
166
+ catch (error) {
167
+ }
168
+ }
169
+ yield device.claimInterface(this.interfaceId);
170
+ });
171
+ }
172
+ post(session, name, data) {
173
+ return __awaiter(this, void 0, void 0, function* () {
174
+ yield this.call(session, name, data);
175
+ });
176
+ }
177
+ call(path, name, data) {
178
+ return __awaiter(this, void 0, void 0, function* () {
179
+ if (this.messages == null) {
180
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportNotConfigured);
181
+ }
182
+ const device = yield this.findDevice(path);
183
+ if (!device) {
184
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceNotFound);
185
+ }
186
+ const { messages } = this;
187
+ if (transport.LogBlockCommand.has(name)) {
188
+ this.Log.debug('call-', ' name: ', name);
189
+ }
190
+ else {
191
+ this.Log.debug('call-', ' name: ', name, ' data: ', data);
192
+ }
193
+ const encodeBuffers = buildEncodeBuffers(messages, name, data);
194
+ for (const buffer of encodeBuffers) {
195
+ const newArray = new Uint8Array(PACKET_SIZE);
196
+ newArray[0] = 63;
197
+ newArray.set(new Uint8Array(buffer), 1);
198
+ if (!device.opened) {
199
+ yield this.connect(path, false);
200
+ }
201
+ yield device.transferOut(this.endpointId, newArray);
202
+ }
203
+ const resData = yield this.receiveData(path);
204
+ if (typeof resData !== 'string') {
205
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.NetworkError, 'Returning data is not string.');
206
+ }
207
+ const jsonData = receiveOne$1(messages, resData);
208
+ return check$1.call(jsonData);
209
+ });
210
+ }
211
+ receiveData(path) {
212
+ var _a;
213
+ return __awaiter(this, void 0, void 0, function* () {
214
+ const device = yield this.findDevice(path);
215
+ if (!device.opened) {
216
+ yield this.connect(path, false);
217
+ }
218
+ const firstPacket = yield device.transferIn(this.endpointId, PACKET_SIZE);
219
+ const firstData = (_a = firstPacket.data) === null || _a === void 0 ? void 0 : _a.buffer.slice(1);
220
+ console.log('receive first packet: ', firstPacket);
221
+ const { length, typeId, restBuffer } = decodeProtocol.decodeChunked(firstData);
222
+ console.log('chunk length: ', length);
223
+ const lengthWithHeader = Number(length + HEADER_LENGTH);
224
+ const decoded = new ByteBuffer__default["default"](lengthWithHeader);
225
+ decoded.writeUint16(typeId);
226
+ decoded.writeUint32(length);
227
+ if (length) {
228
+ decoded.append(restBuffer);
229
+ }
230
+ console.log('first decoded: ', decoded);
231
+ while (decoded.offset < lengthWithHeader) {
232
+ const res = yield device.transferIn(this.endpointId, PACKET_SIZE);
233
+ if (!res.data) {
234
+ throw new Error('no data');
235
+ }
236
+ if (res.data.byteLength === 0) {
237
+ console.warn('empty data');
238
+ }
239
+ const buffer = res.data.buffer.slice(1);
240
+ if (lengthWithHeader - decoded.offset >= PACKET_SIZE) {
241
+ decoded.append(buffer);
242
+ }
243
+ else {
244
+ decoded.append(buffer.slice(0, lengthWithHeader - decoded.offset));
245
+ }
246
+ }
247
+ decoded.reset();
248
+ const result = decoded.toBuffer();
249
+ return Buffer.from(result).toString('hex');
250
+ });
251
+ }
252
+ release(path) {
253
+ return __awaiter(this, void 0, void 0, function* () {
254
+ const device = yield this.findDevice(path);
255
+ yield device.releaseInterface(this.interfaceId);
256
+ yield device.close();
257
+ });
258
+ }
259
+ }
260
+
261
+ const { parseConfigure, buildBuffers, receiveOne, check } = transport__default["default"];
262
+ class ElectronBleTransport {
263
+ constructor() {
264
+ this.name = 'ElectronBleTransport';
265
+ this.configured = false;
266
+ this.runPromise = null;
267
+ this.deviceList = [];
268
+ this.transportCache = {};
269
+ this.lastLoggedDevices = '';
270
+ }
271
+ init(logger, emitter) {
272
+ this.Log = logger;
273
+ this.emitter = emitter;
274
+ if (!navigator.bluetooth) {
275
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Web Bluetooth is not supported by current browser');
276
+ }
277
+ }
278
+ configure(signedData) {
279
+ const messages = parseConfigure(signedData);
280
+ this.configured = true;
281
+ this._messages = messages;
282
+ }
283
+ listen() { }
284
+ logDeviceListIfChanged(devices, scenario, additionalInfo) {
285
+ var _a;
286
+ const sortedDevices = [...devices].sort((a, b) => a.id.localeCompare(b.id));
287
+ const deviceListString = JSON.stringify(sortedDevices.map(d => ({ id: d.id, name: d.name })));
288
+ if (deviceListString !== this.lastLoggedDevices) {
289
+ const prefix = scenario === 'enumerate'
290
+ ? '[Transport] Received new devices'
291
+ : '[Transport] Received devices in acquire';
292
+ const message = additionalInfo ? `${prefix} (${additionalInfo}):` : `${prefix}:`;
293
+ (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug(message, devices);
294
+ this.lastLoggedDevices = deviceListString;
295
+ return true;
296
+ }
297
+ return false;
298
+ }
299
+ enumerate() {
300
+ var _a, _b, _c, _d, _e, _f;
301
+ return __awaiter(this, void 0, void 0, function* () {
302
+ (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[Transport] Starting enumerate');
303
+ try {
304
+ (_b = this.Log) === null || _b === void 0 ? void 0 : _b.debug('[Transport] Checking desktopApi:', window.desktopApi);
305
+ if (!((_c = window.desktopApi) === null || _c === void 0 ? void 0 : _c.onBleSelect)) {
306
+ console.error('[Transport] desktopApi.onBleSelect not available');
307
+ throw new Error('desktopApi.onBleSelect not available');
308
+ }
309
+ (_e = (_d = window.desktopApi) === null || _d === void 0 ? void 0 : _d.clearPreSelect) === null || _e === void 0 ? void 0 : _e.call(_d);
310
+ const deviceSet = new Set();
311
+ const devices = [];
312
+ this.lastLoggedDevices = '';
313
+ return yield new Promise(resolve => {
314
+ var _a, _b;
315
+ (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[Transport] Setting up device scanning with 3s timeout');
316
+ const cleanupAll = () => {
317
+ var _a, _b;
318
+ (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[Transport] Cleaning up resources');
319
+ clearTimeout(timeoutId);
320
+ cleanup === null || cleanup === void 0 ? void 0 : cleanup();
321
+ (_b = window.desktopApi) === null || _b === void 0 ? void 0 : _b.stopBleScan();
322
+ };
323
+ const timeoutId = setTimeout(() => {
324
+ var _a;
325
+ (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[Transport] Scan timeout, returning devices:', devices);
326
+ cleanupAll();
327
+ resolve(devices);
328
+ }, 3000);
329
+ const cleanup = (_b = window.desktopApi) === null || _b === void 0 ? void 0 : _b.onBleSelect(newDevices => {
330
+ this.logDeviceListIfChanged(newDevices, 'enumerate');
331
+ newDevices.forEach(device => {
332
+ var _a;
333
+ const deviceKey = `${device.id}-${device.name}`;
334
+ if (!deviceSet.has(deviceKey)) {
335
+ deviceSet.add(deviceKey);
336
+ devices.push(device);
337
+ (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[Transport] Added new device:', device);
338
+ }
339
+ });
340
+ });
341
+ navigator.bluetooth
342
+ .requestDevice({
343
+ filters: [{ services: [hdShared.ONEKEY_SERVICE_UUID] }],
344
+ optionalServices: [hdShared.ONEKEY_SERVICE_UUID],
345
+ })
346
+ .catch(error => {
347
+ var _a;
348
+ (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[Transport] RequestDevice error (expected):', error);
349
+ });
350
+ });
351
+ }
352
+ catch (error) {
353
+ (_f = window.desktopApi) === null || _f === void 0 ? void 0 : _f.stopBleScan();
354
+ console.error('[Transport] Error in enumerate:', error);
355
+ throw error;
356
+ }
357
+ });
358
+ }
359
+ addDisconnectListener(device) {
360
+ var _a;
361
+ (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[Transport] Adding disconnect listener for device:', device.id);
362
+ device.addEventListener('gattserverdisconnected', () => {
363
+ var _a, _b;
364
+ (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[Transport] Device disconnected:', device.id);
365
+ delete this.transportCache[device.id];
366
+ (_b = this.emitter) === null || _b === void 0 ? void 0 : _b.emit('device-disconnect', {
367
+ name: device.name,
368
+ id: device.id,
369
+ connectId: device.id,
370
+ });
371
+ });
372
+ }
373
+ _monitorCharacteristic(characteristic, deviceId) {
374
+ let bufferLength = 0;
375
+ let buffer = [];
376
+ const subscription = (event) => {
377
+ var _a, _b, _c;
378
+ const { value } = event.target;
379
+ if (!value)
380
+ return;
381
+ (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[Transport] Received notification from device:', deviceId, value);
382
+ try {
383
+ const data = new Uint8Array(value.buffer);
384
+ (_b = this.Log) === null || _b === void 0 ? void 0 : _b.debug('[Transport] Received a packet, buffer:', data);
385
+ if (hdShared.isHeaderChunk(data)) {
386
+ const dataView = new DataView(value.buffer);
387
+ bufferLength = dataView.getInt32(5, false);
388
+ buffer = [...data.subarray(3)];
389
+ }
390
+ else {
391
+ buffer = buffer.concat([...data]);
392
+ }
393
+ if (buffer.length - transport.COMMON_HEADER_SIZE >= bufferLength) {
394
+ const completeBuffer = new Uint8Array(buffer);
395
+ (_c = this.Log) === null || _c === void 0 ? void 0 : _c.debug('[Transport] Received complete packet, resolving Promise');
396
+ bufferLength = 0;
397
+ buffer = [];
398
+ const hexString = Array.from(completeBuffer)
399
+ .map(b => b.toString(16).padStart(2, '0'))
400
+ .join('');
401
+ if (this.runPromise) {
402
+ this.runPromise.resolve(hexString);
403
+ }
404
+ }
405
+ }
406
+ catch (error) {
407
+ console.error('[Transport] Monitor data error:', error);
408
+ if (this.runPromise) {
409
+ this.runPromise.reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleWriteCharacteristicError));
410
+ }
411
+ }
412
+ };
413
+ characteristic.addEventListener('characteristicvaluechanged', subscription);
414
+ return subscription;
415
+ }
416
+ findDevice(id) {
417
+ return this.deviceList.find(d => d.id === id);
418
+ }
419
+ acquire(input) {
420
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9;
421
+ return __awaiter(this, void 0, void 0, function* () {
422
+ const { uuid, forceCleanRunPromise } = input;
423
+ if (!uuid) {
424
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleRequiredUUID);
425
+ }
426
+ (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[Transport] Acquiring device:', uuid);
427
+ this.lastLoggedDevices = '';
428
+ const existingTransport = this.transportCache[uuid];
429
+ if (existingTransport) {
430
+ const { server, device } = existingTransport;
431
+ (_b = this.Log) === null || _b === void 0 ? void 0 : _b.debug('[Transport] Found existing transport, checking connection status');
432
+ (_c = this.Log) === null || _c === void 0 ? void 0 : _c.debug('[Transport] Device GATT connected:', (_d = device.gatt) === null || _d === void 0 ? void 0 : _d.connected);
433
+ (_e = this.Log) === null || _e === void 0 ? void 0 : _e.debug('[Transport] Server connected:', server === null || server === void 0 ? void 0 : server.connected);
434
+ if (!((_f = device.gatt) === null || _f === void 0 ? void 0 : _f.connected) || !(server === null || server === void 0 ? void 0 : server.connected)) {
435
+ (_g = this.Log) === null || _g === void 0 ? void 0 : _g.debug('[Transport] Connection is stale, cleaning up...');
436
+ yield this.release(uuid);
437
+ }
438
+ else {
439
+ (_h = this.Log) === null || _h === void 0 ? void 0 : _h.debug('[Transport] Connection is still active, reusing existing transport');
440
+ return { uuid, path: uuid };
441
+ }
442
+ }
443
+ if (forceCleanRunPromise && this.runPromise) {
444
+ this.runPromise.reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleForceCleanRunPromise));
445
+ (_j = this.Log) === null || _j === void 0 ? void 0 : _j.debug('[Transport] Force clean Bluetooth run promise:', forceCleanRunPromise);
446
+ }
447
+ try {
448
+ let deviceInfo = this.findDevice(uuid);
449
+ if (!deviceInfo) {
450
+ (_k = this.Log) === null || _k === void 0 ? void 0 : _k.debug('[Transport] Device not found in cache, requesting user to select device');
451
+ if (!((_l = window.desktopApi) === null || _l === void 0 ? void 0 : _l.onBleSelect)) {
452
+ throw new Error('desktopApi.onBleSelect not available');
453
+ }
454
+ deviceInfo = yield new Promise((resolve, reject) => {
455
+ var _a, _b, _c;
456
+ let resolved = false;
457
+ let targetDeviceName = null;
458
+ (_b = (_a = window.desktopApi) === null || _a === void 0 ? void 0 : _a.preSelectDevice) === null || _b === void 0 ? void 0 : _b.call(_a, uuid);
459
+ const cleanupAndResolve = (deviceInfo) => {
460
+ var _a, _b;
461
+ if (resolved)
462
+ return;
463
+ resolved = true;
464
+ cleanup === null || cleanup === void 0 ? void 0 : cleanup();
465
+ clearTimeout(timeoutId);
466
+ (_b = (_a = window.desktopApi) === null || _a === void 0 ? void 0 : _a.clearPreSelect) === null || _b === void 0 ? void 0 : _b.call(_a);
467
+ resolve(deviceInfo);
468
+ };
469
+ const cleanupAndReject = (error) => {
470
+ var _a, _b, _c;
471
+ if (resolved)
472
+ return;
473
+ resolved = true;
474
+ cleanup === null || cleanup === void 0 ? void 0 : cleanup();
475
+ clearTimeout(timeoutId);
476
+ (_a = window.desktopApi) === null || _a === void 0 ? void 0 : _a.stopBleScan();
477
+ (_c = (_b = window.desktopApi) === null || _b === void 0 ? void 0 : _b.clearPreSelect) === null || _c === void 0 ? void 0 : _c.call(_b);
478
+ reject(error);
479
+ };
480
+ const cleanup = (_c = window.desktopApi) === null || _c === void 0 ? void 0 : _c.onBleSelect(devices => {
481
+ var _a;
482
+ this.logDeviceListIfChanged(devices, 'acquire', `target: ${uuid}`);
483
+ const targetDevice = devices.find(device => device.id === uuid);
484
+ if (targetDevice) {
485
+ targetDeviceName = targetDevice.name;
486
+ (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[Transport] Target device name for matching:', targetDeviceName);
487
+ }
488
+ });
489
+ navigator.bluetooth
490
+ .requestDevice({
491
+ filters: [{ services: [hdShared.ONEKEY_SERVICE_UUID] }],
492
+ optionalServices: [hdShared.ONEKEY_SERVICE_UUID],
493
+ })
494
+ .then(selectedDevice => {
495
+ var _a, _b;
496
+ (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[Transport] Device selected from browser:', selectedDevice.id, selectedDevice.name, 'Target UUID:', uuid, 'Target name:', targetDeviceName);
497
+ if (targetDeviceName && selectedDevice.name !== targetDeviceName) {
498
+ (_b = this.Log) === null || _b === void 0 ? void 0 : _b.debug('[Transport] Selected device name does not match target:', selectedDevice.name, 'vs', targetDeviceName);
499
+ cleanupAndReject(new Error(`Selected device name "${selectedDevice.name}" does not match target name "${targetDeviceName}"`));
500
+ return;
501
+ }
502
+ cleanupAndResolve({
503
+ id: selectedDevice.id,
504
+ name: selectedDevice.name || 'Unknown Device',
505
+ device: selectedDevice,
506
+ originalUuid: uuid,
507
+ });
508
+ })
509
+ .catch(error => {
510
+ console.error('[Transport] RequestDevice error:', error);
511
+ });
512
+ const timeoutId = setTimeout(() => {
513
+ var _a;
514
+ (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[Transport] Acquire timeout - v2 - waiting for device selection');
515
+ cleanupAndReject(new Error('Acquire device timeout'));
516
+ }, 5000);
517
+ });
518
+ if (!deviceInfo) {
519
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceNotFound);
520
+ }
521
+ (_o = (_m = window.desktopApi) === null || _m === void 0 ? void 0 : _m.clearPreSelect) === null || _o === void 0 ? void 0 : _o.call(_m);
522
+ }
523
+ const { device } = deviceInfo;
524
+ this.addDisconnectListener(device);
525
+ let server;
526
+ try {
527
+ (_p = this.Log) === null || _p === void 0 ? void 0 : _p.debug('[Transport] Start connecting to device:', device.id);
528
+ server = yield ((_q = device.gatt) === null || _q === void 0 ? void 0 : _q.connect());
529
+ (_r = this.Log) === null || _r === void 0 ? void 0 : _r.debug('[Transport] Device gatt available:', !!device.gatt);
530
+ (_s = this.Log) === null || _s === void 0 ? void 0 : _s.debug('[Transport] Device gatt connected:', (_t = device.gatt) === null || _t === void 0 ? void 0 : _t.connected);
531
+ (_u = this.Log) === null || _u === void 0 ? void 0 : _u.debug('[Transport] Connected to device:', server);
532
+ }
533
+ catch (e) {
534
+ (_v = this.Log) === null || _v === void 0 ? void 0 : _v.debug('[Transport] Connect to device error:', e);
535
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleConnectedError, e.message || e);
536
+ }
537
+ if (!server) {
538
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleConnectedError, 'Unable to connect to device');
539
+ }
540
+ let service;
541
+ try {
542
+ (_w = this.Log) === null || _w === void 0 ? void 0 : _w.debug('[Transport] Start getting service:', hdShared.ONEKEY_SERVICE_UUID);
543
+ service = yield server.getPrimaryService(hdShared.ONEKEY_SERVICE_UUID);
544
+ (_x = this.Log) === null || _x === void 0 ? void 0 : _x.debug('[Transport] Got service:', service);
545
+ }
546
+ catch (e) {
547
+ (_y = this.Log) === null || _y === void 0 ? void 0 : _y.debug('[Transport] Get service error:', e);
548
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleServiceNotFound);
549
+ }
550
+ let writeCharacteristic;
551
+ let notifyCharacteristic;
552
+ try {
553
+ (_z = this.Log) === null || _z === void 0 ? void 0 : _z.debug('[Transport] Start getting write characteristic:', hdShared.ONEKEY_WRITE_CHARACTERISTIC_UUID);
554
+ writeCharacteristic = yield service.getCharacteristic(hdShared.ONEKEY_WRITE_CHARACTERISTIC_UUID);
555
+ (_0 = this.Log) === null || _0 === void 0 ? void 0 : _0.debug('[Transport] Got write characteristic:', writeCharacteristic);
556
+ (_1 = this.Log) === null || _1 === void 0 ? void 0 : _1.debug('[Transport] Start getting notify characteristic:', hdShared.ONEKEY_NOTIFY_CHARACTERISTIC_UUID);
557
+ notifyCharacteristic = yield service.getCharacteristic(hdShared.ONEKEY_NOTIFY_CHARACTERISTIC_UUID);
558
+ (_2 = this.Log) === null || _2 === void 0 ? void 0 : _2.debug('[Transport] Got notify characteristic:', notifyCharacteristic);
559
+ }
560
+ catch (e) {
561
+ (_3 = this.Log) === null || _3 === void 0 ? void 0 : _3.debug('[Transport] Get characteristic error:', e);
562
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleCharacteristicNotFound);
563
+ }
564
+ if (!writeCharacteristic.properties.write &&
565
+ !writeCharacteristic.properties.writeWithoutResponse) {
566
+ throw hdShared.ERRORS.TypedError('BLECharacteristicNotWritable: write characteristic not writable');
567
+ }
568
+ if (!notifyCharacteristic.properties.notify) {
569
+ throw hdShared.ERRORS.TypedError('BLECharacteristicNotNotifiable: notify characteristic not notifiable');
570
+ }
571
+ const transport = {
572
+ device,
573
+ server,
574
+ service,
575
+ writeCharacteristic,
576
+ notifyCharacteristic,
577
+ notifySubscription: null,
578
+ };
579
+ (_4 = this.Log) === null || _4 === void 0 ? void 0 : _4.debug('[Transport] Created transport:', transport);
580
+ try {
581
+ (_5 = this.Log) === null || _5 === void 0 ? void 0 : _5.debug('[Transport] Start notifications:', notifyCharacteristic);
582
+ yield notifyCharacteristic.startNotifications();
583
+ (_6 = this.Log) === null || _6 === void 0 ? void 0 : _6.debug('[Transport] Started notifications:', notifyCharacteristic);
584
+ transport.notifySubscription = this._monitorCharacteristic(notifyCharacteristic, uuid);
585
+ }
586
+ catch (e) {
587
+ (_7 = this.Log) === null || _7 === void 0 ? void 0 : _7.debug('[Transport] Start notifications error:', e);
588
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleCharacteristicNotifyError);
589
+ }
590
+ this.transportCache[uuid] = transport;
591
+ if (!this.findDevice(uuid)) {
592
+ this.deviceList.push(deviceInfo);
593
+ }
594
+ (_8 = this.emitter) === null || _8 === void 0 ? void 0 : _8.emit('device-connect', {
595
+ name: device.name,
596
+ id: device.id,
597
+ connectId: device.id,
598
+ });
599
+ return { uuid, path: uuid };
600
+ }
601
+ catch (error) {
602
+ console.error('[Transport] Error acquiring device:', error);
603
+ (_9 = window.desktopApi) === null || _9 === void 0 ? void 0 : _9.stopBleScan();
604
+ throw error;
605
+ }
606
+ });
607
+ }
608
+ release(id) {
609
+ var _a, _b, _c;
610
+ return __awaiter(this, void 0, void 0, function* () {
611
+ const transport = this.transportCache[id];
612
+ if (!transport)
613
+ return;
614
+ const { notifyCharacteristic, notifySubscription } = transport;
615
+ try {
616
+ if (notifyCharacteristic && notifySubscription) {
617
+ (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[Transport] Removing notification listener for device:', id);
618
+ notifyCharacteristic.removeEventListener('characteristicvaluechanged', notifySubscription);
619
+ try {
620
+ yield notifyCharacteristic.stopNotifications();
621
+ }
622
+ catch (e) {
623
+ (_b = this.Log) === null || _b === void 0 ? void 0 : _b.debug('[Transport] Stop notifications error (ignored):', e);
624
+ }
625
+ }
626
+ delete this.transportCache[id];
627
+ (_c = this.Log) === null || _c === void 0 ? void 0 : _c.debug('[Transport] Device released (connection kept alive):', id);
628
+ }
629
+ catch (error) {
630
+ console.error('[Transport] Error releasing device:', error);
631
+ delete this.transportCache[id];
632
+ }
633
+ });
634
+ }
635
+ call(uuid, name, data) {
636
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
637
+ return __awaiter(this, void 0, void 0, function* () {
638
+ if (this._messages == null) {
639
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportNotConfigured);
640
+ }
641
+ const forceRun = name === 'Initialize' || name === 'Cancel';
642
+ (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('electron-ble-transport call this.runPromise', this.runPromise);
643
+ if (this.runPromise && !forceRun) {
644
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportCallInProgress);
645
+ }
646
+ const transport$1 = this.transportCache[uuid];
647
+ if (!transport$1) {
648
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportNotFound);
649
+ }
650
+ const { device, server } = transport$1;
651
+ if (!((_b = device.gatt) === null || _b === void 0 ? void 0 : _b.connected) || !(server === null || server === void 0 ? void 0 : server.connected)) {
652
+ (_c = this.Log) === null || _c === void 0 ? void 0 : _c.debug('[Transport] Connection lost during call, device needs to be re-acquired');
653
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceNotBonded, 'Device connection lost, please re-acquire device');
654
+ }
655
+ this.runPromise = hdShared.createDeferred();
656
+ const messages = this._messages;
657
+ if (name === 'ResourceUpdate' || name === 'ResourceAck') {
658
+ (_d = this.Log) === null || _d === void 0 ? void 0 : _d.debug('electron-ble-transport', 'call-', ' name: ', name, ' data: ', {
659
+ file_name: data === null || data === void 0 ? void 0 : data.file_name,
660
+ hash: data === null || data === void 0 ? void 0 : data.hash,
661
+ });
662
+ }
663
+ else if (transport.LogBlockCommand.has(name)) {
664
+ (_e = this.Log) === null || _e === void 0 ? void 0 : _e.debug('electron-ble-transport', 'call-', ' name: ', name);
665
+ }
666
+ else {
667
+ (_f = this.Log) === null || _f === void 0 ? void 0 : _f.debug('electron-ble-transport', 'call-', ' name: ', name, ' data: ', data);
668
+ }
669
+ const buffers = buildBuffers(messages, name, data);
670
+ function writeChunkedData(buffers, writeFunction, onError) {
671
+ return __awaiter(this, void 0, void 0, function* () {
672
+ const packetCapacity = 512;
673
+ let index = 0;
674
+ let chunk = ByteBuffer__default["default"].allocate(packetCapacity);
675
+ while (index < buffers.length) {
676
+ const buffer = buffers[index].toBuffer();
677
+ chunk.append(buffer);
678
+ index += 1;
679
+ if (chunk.offset === packetCapacity || index >= buffers.length) {
680
+ chunk.reset();
681
+ try {
682
+ const arrayBuffer = chunk.toArrayBuffer();
683
+ yield writeFunction(arrayBuffer);
684
+ chunk = ByteBuffer__default["default"].allocate(packetCapacity);
685
+ }
686
+ catch (e) {
687
+ onError(e);
688
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleWriteCharacteristicError);
689
+ }
690
+ }
691
+ }
692
+ });
693
+ }
694
+ try {
695
+ if (name === 'EmmcFileWrite') {
696
+ yield writeChunkedData(buffers, (data) => __awaiter(this, void 0, void 0, function* () {
697
+ let retries = 3;
698
+ while (retries > 0) {
699
+ try {
700
+ yield transport$1.writeCharacteristic.writeValueWithoutResponse(data);
701
+ break;
702
+ }
703
+ catch (e) {
704
+ retries--;
705
+ if (retries === 0)
706
+ throw e;
707
+ yield new Promise(resolve => setTimeout(resolve, 100));
708
+ }
709
+ }
710
+ }), e => {
711
+ var _a;
712
+ this.runPromise = null;
713
+ (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('writeCharacteristic write error: ', e);
714
+ });
715
+ }
716
+ else if (name === 'FirmwareUpload') {
717
+ yield writeChunkedData(buffers, (data) => __awaiter(this, void 0, void 0, function* () {
718
+ yield transport$1.writeCharacteristic.writeValueWithoutResponse(data);
719
+ }), e => {
720
+ var _a;
721
+ this.runPromise = null;
722
+ (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('writeCharacteristic write error: ', e);
723
+ });
724
+ }
725
+ else {
726
+ for (const buffer of buffers) {
727
+ const arrayBuffer = buffer.toArrayBuffer();
728
+ try {
729
+ yield transport$1.writeCharacteristic.writeValueWithoutResponse(arrayBuffer);
730
+ }
731
+ catch (e) {
732
+ (_g = this.Log) === null || _g === void 0 ? void 0 : _g.debug('writeCharacteristic write error: ', e);
733
+ this.runPromise = null;
734
+ if (e.name === 'NetworkError' || ((_h = e.message) === null || _h === void 0 ? void 0 : _h.includes('disconnected'))) {
735
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceNotBonded);
736
+ }
737
+ else if (e.name === 'NotSupportedError') {
738
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleWriteCharacteristicError, e.message);
739
+ }
740
+ else {
741
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleWriteCharacteristicError);
742
+ }
743
+ }
744
+ }
745
+ }
746
+ const response = yield this.runPromise.promise;
747
+ if (typeof response !== 'string') {
748
+ throw new Error('Returning data is not string.');
749
+ }
750
+ (_j = this.Log) === null || _j === void 0 ? void 0 : _j.debug('receive data: ', response);
751
+ const jsonData = receiveOne(messages, response);
752
+ return check.call(jsonData);
753
+ }
754
+ catch (e) {
755
+ (_k = this.Log) === null || _k === void 0 ? void 0 : _k.debug('call error: ', e);
756
+ throw e;
757
+ }
758
+ finally {
759
+ this.runPromise = null;
760
+ }
761
+ });
762
+ }
763
+ }
764
+
765
+ exports.ElectronBleTransport = ElectronBleTransport;
766
+ exports.WebUsbTransport = WebUsbTransport;