@onekeyfe/hd-core 1.2.0-alpha.170 → 1.2.0-alpha.172
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__/firmware-update/firmware-update-v4-install-poll.test.ts +86 -3
- package/__tests__/pro2Wallpaper.test.ts +0 -66
- package/__tests__/protocol-v2.test.ts +58 -42
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts +1 -2
- package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts.map +1 -1
- package/dist/index.d.ts +1 -4
- package/dist/index.js +39 -184
- package/dist/utils/pro2Wallpaper.d.ts +1 -3
- package/dist/utils/pro2Wallpaper.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/FirmwareUpdateV4.ts +50 -26
- package/src/api/protocol-v2/DeviceUploadWallpaper.ts +2 -12
- package/src/utils/pro2Wallpaper.ts +1 -197
|
@@ -14,12 +14,12 @@ describe('FirmwareUpdateV4 install polling', () => {
|
|
|
14
14
|
jest.restoreAllMocks();
|
|
15
15
|
});
|
|
16
16
|
|
|
17
|
-
test('
|
|
17
|
+
test('keeps USB on Stage, Request Success, then status polling', async () => {
|
|
18
18
|
const method = new FirmwareUpdateV4({
|
|
19
19
|
id: 1,
|
|
20
20
|
payload: {
|
|
21
21
|
method: 'firmwareUpdateV4',
|
|
22
|
-
connectId: 'pro2-
|
|
22
|
+
connectId: 'pro2-usb',
|
|
23
23
|
},
|
|
24
24
|
});
|
|
25
25
|
const targets = [{ target_id: 4, path: 'vol0:/application_p1.bin' }];
|
|
@@ -43,7 +43,7 @@ describe('FirmwareUpdateV4 install polling', () => {
|
|
|
43
43
|
method.device = {
|
|
44
44
|
getCommands: () => ({ typedCall }),
|
|
45
45
|
createProtocolV2UiPhaseMetadata: jest.fn().mockReturnValue(undefined),
|
|
46
|
-
toMessageObject: jest.fn().mockReturnValue({ connectId: 'pro2-
|
|
46
|
+
toMessageObject: jest.fn().mockReturnValue({ connectId: 'pro2-usb' }),
|
|
47
47
|
setCancelableAction: jest.fn(),
|
|
48
48
|
clearCancelableAction: jest.fn(),
|
|
49
49
|
} as unknown as Device;
|
|
@@ -59,6 +59,7 @@ describe('FirmwareUpdateV4 install polling', () => {
|
|
|
59
59
|
};
|
|
60
60
|
firmwareUpdate.reconnectProtocolV2Device = jest.fn().mockResolvedValue(undefined);
|
|
61
61
|
firmwareUpdate.verifyProtocolV2ReconnectIdentity = jest.fn().mockResolvedValue({});
|
|
62
|
+
(method as any).isBleReconnect = jest.fn(() => false);
|
|
62
63
|
|
|
63
64
|
await firmwareUpdate.protocolV2StartFirmwareUpdate({ targets });
|
|
64
65
|
await firmwareUpdate.waitForProtocolV2FirmwareUpdateComplete(targets);
|
|
@@ -72,6 +73,88 @@ describe('FirmwareUpdateV4 install polling', () => {
|
|
|
72
73
|
);
|
|
73
74
|
});
|
|
74
75
|
|
|
76
|
+
test('writes the BLE Request and completes only from target status polling', async () => {
|
|
77
|
+
const method = new FirmwareUpdateV4({
|
|
78
|
+
id: 1,
|
|
79
|
+
payload: {
|
|
80
|
+
method: 'firmwareUpdateV4',
|
|
81
|
+
connectId: 'pro2-ble',
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
const targets = [{ target_id: 6, path: 'vol0:/coprocessor.bin' }];
|
|
85
|
+
const typedCall = jest
|
|
86
|
+
.fn()
|
|
87
|
+
.mockResolvedValueOnce({ type: 'Success', message: {} })
|
|
88
|
+
.mockResolvedValueOnce({
|
|
89
|
+
type: 'DeviceFirmwareUpdateStatus',
|
|
90
|
+
message: {
|
|
91
|
+
records: [
|
|
92
|
+
{
|
|
93
|
+
target_id: 6,
|
|
94
|
+
status: 'FW_MGMT_UPDATER_TASK_STATUS_IN_PROGRESS',
|
|
95
|
+
path: 'vol0:/coprocessor.bin',
|
|
96
|
+
},
|
|
97
|
+
],
|
|
98
|
+
},
|
|
99
|
+
})
|
|
100
|
+
.mockResolvedValueOnce({
|
|
101
|
+
type: 'DeviceFirmwareUpdateStatus',
|
|
102
|
+
message: {
|
|
103
|
+
records: [
|
|
104
|
+
{
|
|
105
|
+
target_id: 6,
|
|
106
|
+
status: 'FW_MGMT_UPDATER_TASK_STATUS_FINISHED',
|
|
107
|
+
path: 'vol0:/coprocessor.bin',
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
const call = jest.fn().mockResolvedValue({
|
|
113
|
+
type: 'WriteCompleted',
|
|
114
|
+
message: {},
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
method.device = {
|
|
118
|
+
getCommands: () => ({ typedCall, call }),
|
|
119
|
+
createProtocolV2UiPhaseMetadata: jest.fn().mockReturnValue(undefined),
|
|
120
|
+
toMessageObject: jest.fn().mockReturnValue({ connectId: 'pro2-ble' }),
|
|
121
|
+
setCancelableAction: jest.fn(),
|
|
122
|
+
clearCancelableAction: jest.fn(),
|
|
123
|
+
} as unknown as Device;
|
|
124
|
+
method.postMessage = jest.fn();
|
|
125
|
+
method.postProgressMessage = jest.fn();
|
|
126
|
+
(method as any).isBleReconnect = jest.fn(() => true);
|
|
127
|
+
|
|
128
|
+
const firmwareUpdate = method as unknown as {
|
|
129
|
+
protocolV2StartFirmwareUpdate: (params: { targets: typeof targets }) => Promise<void>;
|
|
130
|
+
waitForProtocolV2FirmwareUpdateComplete: (
|
|
131
|
+
value: typeof targets,
|
|
132
|
+
requireCurrentInstallStatus: boolean
|
|
133
|
+
) => Promise<void>;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
await firmwareUpdate.protocolV2StartFirmwareUpdate({ targets });
|
|
137
|
+
|
|
138
|
+
expect(typedCall).toHaveBeenCalledTimes(1);
|
|
139
|
+
expect(typedCall).toHaveBeenCalledWith('DeviceFirmwareUpdateStage', 'Success', { targets });
|
|
140
|
+
expect(call).toHaveBeenCalledWith(
|
|
141
|
+
'DeviceFirmwareUpdateRequest',
|
|
142
|
+
{},
|
|
143
|
+
expect.objectContaining({
|
|
144
|
+
returnAfterWrite: true,
|
|
145
|
+
expectedTypes: ['Success'],
|
|
146
|
+
onResponseAfterWrite: expect.any(Function),
|
|
147
|
+
})
|
|
148
|
+
);
|
|
149
|
+
expect(method.postProgressMessage).not.toHaveBeenCalled();
|
|
150
|
+
|
|
151
|
+
await firmwareUpdate.waitForProtocolV2FirmwareUpdateComplete(targets, true);
|
|
152
|
+
|
|
153
|
+
expect(typedCall.mock.calls[1]?.[0]).toBe('DeviceFirmwareUpdateStatusGet');
|
|
154
|
+
expect(typedCall.mock.calls[1]?.[1]).toBe('DeviceFirmwareUpdateStatus');
|
|
155
|
+
expect(method.postProgressMessage).toHaveBeenCalledWith(100, 'installingFirmware');
|
|
156
|
+
});
|
|
157
|
+
|
|
75
158
|
test('does not send Request when Stage is rejected', async () => {
|
|
76
159
|
const method = new FirmwareUpdateV4({
|
|
77
160
|
id: 1,
|
|
@@ -1,48 +1,5 @@
|
|
|
1
1
|
import { encodePro2Wallpaper } from '../src/utils/pro2Wallpaper';
|
|
2
2
|
|
|
3
|
-
// The test decoder mirrors LZ4's bit-packed token and offset format.
|
|
4
|
-
/* eslint-disable no-bitwise */
|
|
5
|
-
|
|
6
|
-
function decodeLz4Block(data: Uint8Array, expectedLength: number) {
|
|
7
|
-
const output = new Uint8Array(expectedLength);
|
|
8
|
-
let inputOffset = 0;
|
|
9
|
-
let outputOffset = 0;
|
|
10
|
-
|
|
11
|
-
const readLength = (initialLength: number) => {
|
|
12
|
-
let length = initialLength;
|
|
13
|
-
if (length === 0x0f) {
|
|
14
|
-
let extension = 0xff;
|
|
15
|
-
while (extension === 0xff) {
|
|
16
|
-
extension = data[inputOffset];
|
|
17
|
-
inputOffset += 1;
|
|
18
|
-
length += extension;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
return length;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
while (inputOffset < data.byteLength) {
|
|
25
|
-
const token = data[inputOffset];
|
|
26
|
-
inputOffset += 1;
|
|
27
|
-
const literalLength = readLength(token >> 4);
|
|
28
|
-
output.set(data.subarray(inputOffset, inputOffset + literalLength), outputOffset);
|
|
29
|
-
inputOffset += literalLength;
|
|
30
|
-
outputOffset += literalLength;
|
|
31
|
-
if (inputOffset >= data.byteLength) break;
|
|
32
|
-
|
|
33
|
-
const matchOffset = data[inputOffset] | (data[inputOffset + 1] << 8);
|
|
34
|
-
inputOffset += 2;
|
|
35
|
-
const matchLength = readLength(token & 0x0f) + 4;
|
|
36
|
-
for (let index = 0; index < matchLength; index += 1) {
|
|
37
|
-
output[outputOffset] = output[outputOffset - matchOffset];
|
|
38
|
-
outputOffset += 1;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
expect(outputOffset).toBe(expectedLength);
|
|
43
|
-
return output;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
3
|
describe('encodePro2Wallpaper', () => {
|
|
47
4
|
test('encodes opaque pixels as aligned LVGL v9 RGB565 data', () => {
|
|
48
5
|
const result = encodePro2Wallpaper({
|
|
@@ -71,29 +28,6 @@ describe('encodePro2Wallpaper', () => {
|
|
|
71
28
|
expect(Array.from(result.data.slice(12))).toEqual([0x1f, 0x00, 0xff, 0xff, 128, 255]);
|
|
72
29
|
});
|
|
73
30
|
|
|
74
|
-
test('encodes an I8 palette and pixel indices as an LVGL LZ4 block', () => {
|
|
75
|
-
const result = encodePro2Wallpaper({
|
|
76
|
-
width: 2,
|
|
77
|
-
height: 1,
|
|
78
|
-
rgba: new Uint8Array([255, 0, 0, 255, 0, 255, 0, 255]),
|
|
79
|
-
encoding: 'i8-lz4',
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
expect(result.colorFormat).toBe('I8');
|
|
83
|
-
expect(Array.from(result.data.slice(0, 12))).toEqual([
|
|
84
|
-
0x19, 0x0a, 0x08, 0, 2, 0, 1, 0, 2, 0, 0, 0,
|
|
85
|
-
]);
|
|
86
|
-
const view = new DataView(result.data.buffer, result.data.byteOffset, result.data.byteLength);
|
|
87
|
-
expect(view.getUint32(12, true)).toBe(2);
|
|
88
|
-
expect(view.getUint32(16, true)).toBe(result.data.byteLength - 24);
|
|
89
|
-
expect(view.getUint32(20, true)).toBe(1026);
|
|
90
|
-
|
|
91
|
-
const rawData = decodeLz4Block(result.data.slice(24), 1026);
|
|
92
|
-
expect(Array.from(rawData.slice(210 * 4, 210 * 4 + 4))).toEqual([0, 0, 255, 255]);
|
|
93
|
-
expect(Array.from(rawData.slice(36 * 4, 36 * 4 + 4))).toEqual([0, 255, 0, 255]);
|
|
94
|
-
expect(Array.from(rawData.slice(-2))).toEqual([210, 36]);
|
|
95
|
-
});
|
|
96
|
-
|
|
97
31
|
test('rejects invalid dimensions and RGBA byte length', () => {
|
|
98
32
|
expect(() => encodePro2Wallpaper({ width: 0, height: 1, rgba: new Uint8Array() })).toThrow(
|
|
99
33
|
'width'
|
|
@@ -194,13 +194,7 @@ describe('DeviceUploadWallpaper', () => {
|
|
|
194
194
|
refreshProtocolV2SettingsAfterMutation: jest.fn().mockResolvedValue({}),
|
|
195
195
|
});
|
|
196
196
|
|
|
197
|
-
|
|
198
|
-
jest.restoreAllMocks();
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
test('uses I8 with LZ4 when uploading a Pro2 wallpaper over BLE', async () => {
|
|
202
|
-
jest.spyOn(DataManager, 'getSettings').mockReturnValue('lowlevel');
|
|
203
|
-
jest.spyOn(DataManager, 'isBleConnect').mockReturnValue(true);
|
|
197
|
+
test('encodes, uploads and applies a Pro2 wallpaper', async () => {
|
|
204
198
|
const typedCall = jest.fn().mockImplementation((request, _response, params) => {
|
|
205
199
|
if (request === 'FilesystemDirMake') return { message: { message: 'directory ready' } };
|
|
206
200
|
if (request === 'FilesystemFileWrite') {
|
|
@@ -243,7 +237,7 @@ describe('DeviceUploadWallpaper', () => {
|
|
|
243
237
|
});
|
|
244
238
|
expect(device.refreshProtocolV2SettingsAfterMutation).toHaveBeenCalledTimes(1);
|
|
245
239
|
expect(typedCall.mock.calls.some(call => call[0] === 'SetWallpaper')).toBe(false);
|
|
246
|
-
expect(result).toMatchObject({ colorFormat: '
|
|
240
|
+
expect(result).toMatchObject({ colorFormat: 'RGB565', message: 'wallpaper applied' });
|
|
247
241
|
const fileWriteCallCount = typedCall.mock.calls.filter(
|
|
248
242
|
call => call[0] === 'FilesystemFileWrite'
|
|
249
243
|
).length;
|
|
@@ -281,8 +275,6 @@ describe('DeviceUploadWallpaper', () => {
|
|
|
281
275
|
});
|
|
282
276
|
|
|
283
277
|
test('returns success when wallpaper read-back fails after apply', async () => {
|
|
284
|
-
jest.spyOn(DataManager, 'getSettings').mockReturnValue('desktop-webusb');
|
|
285
|
-
jest.spyOn(DataManager, 'isBleConnect').mockReturnValue(false);
|
|
286
278
|
const typedCall = jest.fn().mockImplementation((request, _response, params) => {
|
|
287
279
|
if (request === 'FilesystemDirMake') return { message: {} };
|
|
288
280
|
if (request === 'FilesystemFileWrite') {
|
|
@@ -308,10 +300,7 @@ describe('DeviceUploadWallpaper', () => {
|
|
|
308
300
|
(method as any).device = device;
|
|
309
301
|
method.init();
|
|
310
302
|
|
|
311
|
-
await expect(method.run()).resolves.toMatchObject({
|
|
312
|
-
colorFormat: 'RGB565',
|
|
313
|
-
message: 'wallpaper applied',
|
|
314
|
-
});
|
|
303
|
+
await expect(method.run()).resolves.toMatchObject({ message: 'wallpaper applied' });
|
|
315
304
|
expect(device.refreshProtocolV2SettingsAfterMutation).toHaveBeenCalledTimes(1);
|
|
316
305
|
});
|
|
317
306
|
|
|
@@ -328,19 +317,6 @@ describe('DeviceUploadWallpaper', () => {
|
|
|
328
317
|
expect(() => method.init()).toThrow('fileName');
|
|
329
318
|
});
|
|
330
319
|
|
|
331
|
-
test('rejects unsupported wallpaper encodings before device communication', () => {
|
|
332
|
-
const method = new DeviceUploadWallpaper({
|
|
333
|
-
id: 1,
|
|
334
|
-
payload: {
|
|
335
|
-
method: 'deviceUploadWallpaper',
|
|
336
|
-
jpegBase64: createJpegBase64(604, 1024),
|
|
337
|
-
encoding: 'gzip',
|
|
338
|
-
} as any,
|
|
339
|
-
});
|
|
340
|
-
|
|
341
|
-
expect(() => method.init()).toThrow('encoding');
|
|
342
|
-
});
|
|
343
|
-
|
|
344
320
|
test('rejects unsupported firmware before creating or writing files', async () => {
|
|
345
321
|
const typedCall = jest.fn();
|
|
346
322
|
const method = new DeviceUploadWallpaper({
|
|
@@ -4978,7 +4954,7 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
4978
4954
|
expect(commands.mainId).toBe('usb-path');
|
|
4979
4955
|
});
|
|
4980
4956
|
|
|
4981
|
-
test('
|
|
4957
|
+
test('reacquires the same BLE peripheral by id without scanning during install recovery', async () => {
|
|
4982
4958
|
const method = new FirmwareUpdateV4({
|
|
4983
4959
|
id: 1,
|
|
4984
4960
|
payload: {
|
|
@@ -5000,7 +4976,7 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
5000
4976
|
|
|
5001
4977
|
await (method as any).reconnectProtocolV2Device({ skipProtocolProbe: true });
|
|
5002
4978
|
|
|
5003
|
-
expect(enumerate).
|
|
4979
|
+
expect(enumerate).not.toHaveBeenCalled();
|
|
5004
4980
|
expect(acquire).toHaveBeenCalledWith('ble-id', null, true, 'V2', undefined, undefined, true);
|
|
5005
4981
|
expect(commands.disposed).toBe(false);
|
|
5006
4982
|
expect(commands.mainId).toBe('ble-id');
|
|
@@ -5551,15 +5527,11 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
5551
5527
|
method: 'firmwareUpdateV4',
|
|
5552
5528
|
},
|
|
5553
5529
|
});
|
|
5554
|
-
const typedCall = jest.fn().
|
|
5555
|
-
|
|
5556
|
-
return Promise.reject(new Error('React Native BLE transport released'));
|
|
5557
|
-
}
|
|
5558
|
-
return Promise.resolve({ type: 'Success', message: {} });
|
|
5559
|
-
});
|
|
5530
|
+
const typedCall = jest.fn().mockResolvedValue({ type: 'Success', message: {} });
|
|
5531
|
+
const call = jest.fn().mockRejectedValue(new Error('React Native BLE transport released'));
|
|
5560
5532
|
|
|
5561
5533
|
(method as any).device = stubDevice({
|
|
5562
|
-
getCommands: () => ({ typedCall }),
|
|
5534
|
+
getCommands: () => ({ typedCall, call }),
|
|
5563
5535
|
createProtocolV2UiPhaseMetadata: jest.fn().mockReturnValue(undefined),
|
|
5564
5536
|
toMessageObject: jest.fn().mockReturnValue({ connectId: 'pro2' }),
|
|
5565
5537
|
});
|
|
@@ -5572,7 +5544,16 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
5572
5544
|
})
|
|
5573
5545
|
).resolves.toBeUndefined();
|
|
5574
5546
|
|
|
5575
|
-
expect(
|
|
5547
|
+
expect(call).toHaveBeenCalledWith(
|
|
5548
|
+
'DeviceFirmwareUpdateRequest',
|
|
5549
|
+
{},
|
|
5550
|
+
expect.objectContaining({
|
|
5551
|
+
returnAfterWrite: true,
|
|
5552
|
+
expectedTypes: ['Success'],
|
|
5553
|
+
onResponseAfterWrite: expect.any(Function),
|
|
5554
|
+
})
|
|
5555
|
+
);
|
|
5556
|
+
expect(typedCall).not.toHaveBeenCalledWith('DeviceFirmwareUpdateRequest', 'Success', {});
|
|
5576
5557
|
expect((method as any).protocolV2InstallNeedsBleReconnect).toBe(true);
|
|
5577
5558
|
});
|
|
5578
5559
|
|
|
@@ -5678,7 +5659,7 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
5678
5659
|
expect(method.postProgressMessage).toHaveBeenCalledWith(100, 'installingFirmware');
|
|
5679
5660
|
});
|
|
5680
5661
|
|
|
5681
|
-
test('keeps polling after
|
|
5662
|
+
test('keeps polling after an empty status response until the target finishes', async () => {
|
|
5682
5663
|
const method = new FirmwareUpdateV4({
|
|
5683
5664
|
id: 1,
|
|
5684
5665
|
payload: {
|
|
@@ -5687,7 +5668,10 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
5687
5668
|
});
|
|
5688
5669
|
const typedCall = jest
|
|
5689
5670
|
.fn()
|
|
5690
|
-
.mockResolvedValueOnce({
|
|
5671
|
+
.mockResolvedValueOnce({
|
|
5672
|
+
type: 'DeviceFirmwareUpdateStatus',
|
|
5673
|
+
message: { records: [] },
|
|
5674
|
+
})
|
|
5691
5675
|
.mockResolvedValueOnce({
|
|
5692
5676
|
type: 'DeviceFirmwareUpdateStatus',
|
|
5693
5677
|
message: { records: [] },
|
|
@@ -5829,6 +5813,38 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
5829
5813
|
expect(method.postProgressMessage).toHaveBeenCalledWith(100, 'installingFirmware');
|
|
5830
5814
|
});
|
|
5831
5815
|
|
|
5816
|
+
test('does not count a stale finished target when only another target was live', () => {
|
|
5817
|
+
const method = new FirmwareUpdateV4({
|
|
5818
|
+
id: 1,
|
|
5819
|
+
payload: {
|
|
5820
|
+
method: 'firmwareUpdateV4',
|
|
5821
|
+
},
|
|
5822
|
+
});
|
|
5823
|
+
const assertProtocolV2TargetStatus = (method as any).assertProtocolV2TargetStatus.bind(method);
|
|
5824
|
+
const expectedTargetIds = new Set([3, 4]);
|
|
5825
|
+
const expectedPaths = new Map([
|
|
5826
|
+
[3, 'vol0:/bootloader.bin'],
|
|
5827
|
+
[4, 'vol0:/application_p1.bin'],
|
|
5828
|
+
]);
|
|
5829
|
+
const liveTargetIds = new Set([4]);
|
|
5830
|
+
method.postProgressMessage = jest.fn();
|
|
5831
|
+
|
|
5832
|
+
const completed = assertProtocolV2TargetStatus(
|
|
5833
|
+
[
|
|
5834
|
+
{ target_id: 3, status: 2, path: 'vol0:/bootloader.bin' },
|
|
5835
|
+
{ target_id: 4, status: 2, path: 'vol0:/application_p1.bin' },
|
|
5836
|
+
],
|
|
5837
|
+
expectedTargetIds,
|
|
5838
|
+
expectedPaths,
|
|
5839
|
+
liveTargetIds
|
|
5840
|
+
);
|
|
5841
|
+
|
|
5842
|
+
expect(completed).toBe(false);
|
|
5843
|
+
expect((method as any).protocolV2CompletedTargetIds).toEqual(new Set([4]));
|
|
5844
|
+
expect(method.postProgressMessage).toHaveBeenCalledWith(50, 'installingFirmware');
|
|
5845
|
+
expect(method.postProgressMessage).not.toHaveBeenCalledWith(100, 'installingFirmware');
|
|
5846
|
+
});
|
|
5847
|
+
|
|
5832
5848
|
test('ignores stale failed records until the current install starts', async () => {
|
|
5833
5849
|
const method = new FirmwareUpdateV4({
|
|
5834
5850
|
id: 1,
|
|
@@ -6118,7 +6134,6 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
6118
6134
|
});
|
|
6119
6135
|
const typedCall = jest
|
|
6120
6136
|
.fn()
|
|
6121
|
-
.mockResolvedValueOnce({ type: 'Success', message: {} })
|
|
6122
6137
|
.mockRejectedValueOnce(new Error('Pro2 is rebooting'))
|
|
6123
6138
|
.mockResolvedValueOnce({
|
|
6124
6139
|
type: 'DeviceFirmwareUpdateStatus',
|
|
@@ -6135,6 +6150,7 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
6135
6150
|
(method as any).device = stubDevice({
|
|
6136
6151
|
getCommands: () => ({ typedCall }),
|
|
6137
6152
|
});
|
|
6153
|
+
(method as any).protocolV2InstallRequestConfirmed = true;
|
|
6138
6154
|
(method as any).reconnectProtocolV2Device = jest.fn().mockResolvedValue(undefined);
|
|
6139
6155
|
(method as any).verifyProtocolV2ReconnectIdentity = jest.fn().mockResolvedValue(deviceInfo);
|
|
6140
6156
|
(method as any).probeProtocolV2NormalMode = jest.fn().mockResolvedValue(true);
|
|
@@ -6565,7 +6581,7 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
6565
6581
|
expect(reconnectProtocolV2Device).not.toHaveBeenCalled();
|
|
6566
6582
|
expect(typedCall).toHaveBeenCalledWith(
|
|
6567
6583
|
'DeviceFirmwareUpdateStatusGet',
|
|
6568
|
-
|
|
6584
|
+
'DeviceFirmwareUpdateStatus',
|
|
6569
6585
|
expect.anything(),
|
|
6570
6586
|
expect.anything()
|
|
6571
6587
|
);
|
|
@@ -6847,7 +6863,7 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
6847
6863
|
});
|
|
6848
6864
|
expect(typedCall).toHaveBeenCalledWith(
|
|
6849
6865
|
'DeviceFirmwareUpdateStatusGet',
|
|
6850
|
-
|
|
6866
|
+
'DeviceFirmwareUpdateStatus',
|
|
6851
6867
|
{
|
|
6852
6868
|
fields: {
|
|
6853
6869
|
status: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FirmwareUpdateV4.d.ts","sourceRoot":"","sources":["../../src/api/FirmwareUpdateV4.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAkD,MAAM,qBAAqB,CAAC;AA0BlG,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AA+B/E,OAAO,KAAK,EAEV,sBAAsB,EAEvB,MAAM,6BAA6B,CAAC;AAoErC,wBAAgB,wCAAwC,CACtD,UAAU,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS,EAC5C,MAAM,EAAE,sBAAsB,EAC9B,0BAA0B,UAAQ,QAiCnC;AAuSD,eAAO,MAAM,oCAAoC,WACvC,WAAW,GAAG,UAAU,eACnB,MAAM,GAAG,SAAS,YAKhC,CAAC;AAEF,eAAO,MAAM,iCAAiC,0BACrB,MAAM,uBACR,MAAM,iBACZ,MAAM,eACR,MAAM,SAsBpB,CAAC;AAUF,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,wBAAwB,CAAC,sBAAsB,CAAC;IAC5F,OAAO,CAAC,8BAA8B,CAAC,CAAS;IAEhD,OAAO,CAAC,sBAAsB,CAAC,CAAS;IAExC,OAAO,CAAC,oCAAoC,CAAS;IAErD,qBAAqB;IAIrB,OAAO,CAAC,yBAAyB,CAA4B;IAE7D,OAAO,CAAC,2BAA2B,CAAS;IAE5C,OAAO,CAAC,iCAAiC,CAAS;IAElD,OAAO,CAAC,iCAAiC,CAA6B;IAEtE,OAAO,CAAC,4BAA4B,CAAqB;IAEzD,OAAO,CAAC,6BAA6B,CAAC,CAAW;IAEjD,OAAO,CAAC,+BAA+B,CAAC,CAAuB;IAE/D,OAAO,CAAC,iCAAiC,CAA6B;IAEtE,OAAO,CAAC,kCAAkC,CAAS;IAEnD,OAAO,CAAC,iCAAiC,CAAS;IAElD,OAAO,CAAC,kCAAkC,CAAC,CAAW;IAEtD,OAAO,CAAC,8BAA8B,CAAC,CAAS;IAEhD,OAAO,CAAC,gCAAgC,CAAK;IAE7C,IAAI;IA6LJ,OAAO,CAAC,8BAA8B;IAwBhC,GAAG;;;;;YAKK,aAAa;YA0Ib,4BAA4B;YAkB5B,0BAA0B;YAY1B,8BAA8B;YAK9B,+BAA+B;YAqG/B,4BAA4B;YA+C5B,0CAA0C;YAkB1C,qCAAqC;YAoFrC,gCAAgC;YAgBhC,uCAAuC;YAmDvC,8BAA8B;IA8B5C,OAAO,CAAC,8BAA8B;IA0BtC,OAAO,CAAC,kCAAkC;IAc1C,OAAO,CAAC,gCAAgC;YAuD1B,2BAA2B;IAmBzC,OAAO,CAAC,yBAAyB;IAKjC,OAAO,CAAC,oCAAoC;IAY5C,OAAO,CAAC,4BAA4B;IAUpC,OAAO,CAAC,kCAAkC;IAS1C,OAAO,CAAC,8BAA8B;YAMxB,iCAAiC;YAOjC,iCAAiC;YAmBjC,iCAAiC;IAM/C,OAAO,CAAC,uBAAuB;IAI/B,OAAO,CAAC,mCAAmC;IAe3C,OAAO,CAAC,iCAAiC;IAWzC,OAAO,CAAC,2BAA2B;IAsBnC,OAAO,CAAC,yBAAyB;IAiBjC,OAAO,CAAC,wBAAwB;YAkBlB,iCAAiC;YA6CjC,uCAAuC;YA0CvC,+BAA+B;IAmF7C,OAAO,CAAC,6BAA6B;IAMrC,OAAO,CAAC,gCAAgC;YAM1B,8BAA8B;YAmD9B,kCAAkC;IA+BhD,OAAO,CAAC,0BAA0B;IAUlC,OAAO,CAAC,yBAAyB;YAcnB,4BAA4B;IAkBpC,6BAA6B;YAkBrB,+BAA+B;IAkD7C,OAAO,CAAC,6BAA6B;YAkCvB,6BAA6B;YA0B7B,0CAA0C;YA6B1C,uBAAuB;YAiCvB,8BAA8B;YAwE9B,6BAA6B;IA8E3C,OAAO,CAAC,mCAAmC;YAI7B,0BAA0B;IAaxC,OAAO,CAAC,8BAA8B;IAiBtC,OAAO,CAAC,4BAA4B;
|
|
1
|
+
{"version":3,"file":"FirmwareUpdateV4.d.ts","sourceRoot":"","sources":["../../src/api/FirmwareUpdateV4.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAkD,MAAM,qBAAqB,CAAC;AA0BlG,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AA+B/E,OAAO,KAAK,EAEV,sBAAsB,EAEvB,MAAM,6BAA6B,CAAC;AAoErC,wBAAgB,wCAAwC,CACtD,UAAU,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS,EAC5C,MAAM,EAAE,sBAAsB,EAC9B,0BAA0B,UAAQ,QAiCnC;AAuSD,eAAO,MAAM,oCAAoC,WACvC,WAAW,GAAG,UAAU,eACnB,MAAM,GAAG,SAAS,YAKhC,CAAC;AAEF,eAAO,MAAM,iCAAiC,0BACrB,MAAM,uBACR,MAAM,iBACZ,MAAM,eACR,MAAM,SAsBpB,CAAC;AAUF,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,wBAAwB,CAAC,sBAAsB,CAAC;IAC5F,OAAO,CAAC,8BAA8B,CAAC,CAAS;IAEhD,OAAO,CAAC,sBAAsB,CAAC,CAAS;IAExC,OAAO,CAAC,oCAAoC,CAAS;IAErD,qBAAqB;IAIrB,OAAO,CAAC,yBAAyB,CAA4B;IAE7D,OAAO,CAAC,2BAA2B,CAAS;IAE5C,OAAO,CAAC,iCAAiC,CAAS;IAElD,OAAO,CAAC,iCAAiC,CAA6B;IAEtE,OAAO,CAAC,4BAA4B,CAAqB;IAEzD,OAAO,CAAC,6BAA6B,CAAC,CAAW;IAEjD,OAAO,CAAC,+BAA+B,CAAC,CAAuB;IAE/D,OAAO,CAAC,iCAAiC,CAA6B;IAEtE,OAAO,CAAC,kCAAkC,CAAS;IAEnD,OAAO,CAAC,iCAAiC,CAAS;IAElD,OAAO,CAAC,kCAAkC,CAAC,CAAW;IAEtD,OAAO,CAAC,8BAA8B,CAAC,CAAS;IAEhD,OAAO,CAAC,gCAAgC,CAAK;IAE7C,IAAI;IA6LJ,OAAO,CAAC,8BAA8B;IAwBhC,GAAG;;;;;YAKK,aAAa;YA0Ib,4BAA4B;YAkB5B,0BAA0B;YAY1B,8BAA8B;YAK9B,+BAA+B;YAqG/B,4BAA4B;YA+C5B,0CAA0C;YAkB1C,qCAAqC;YAoFrC,gCAAgC;YAgBhC,uCAAuC;YAmDvC,8BAA8B;IA8B5C,OAAO,CAAC,8BAA8B;IA0BtC,OAAO,CAAC,kCAAkC;IAc1C,OAAO,CAAC,gCAAgC;YAuD1B,2BAA2B;IAmBzC,OAAO,CAAC,yBAAyB;IAKjC,OAAO,CAAC,oCAAoC;IAY5C,OAAO,CAAC,4BAA4B;IAUpC,OAAO,CAAC,kCAAkC;IAS1C,OAAO,CAAC,8BAA8B;YAMxB,iCAAiC;YAOjC,iCAAiC;YAmBjC,iCAAiC;IAM/C,OAAO,CAAC,uBAAuB;IAI/B,OAAO,CAAC,mCAAmC;IAe3C,OAAO,CAAC,iCAAiC;IAWzC,OAAO,CAAC,2BAA2B;IAsBnC,OAAO,CAAC,yBAAyB;IAiBjC,OAAO,CAAC,wBAAwB;YAkBlB,iCAAiC;YA6CjC,uCAAuC;YA0CvC,+BAA+B;IAmF7C,OAAO,CAAC,6BAA6B;IAMrC,OAAO,CAAC,gCAAgC;YAM1B,8BAA8B;YAmD9B,kCAAkC;IA+BhD,OAAO,CAAC,0BAA0B;IAUlC,OAAO,CAAC,yBAAyB;YAcnB,4BAA4B;IAkBpC,6BAA6B;YAkBrB,+BAA+B;IAkD7C,OAAO,CAAC,6BAA6B;YAkCvB,6BAA6B;YA0B7B,0CAA0C;YA6B1C,uBAAuB;YAiCvB,8BAA8B;YAwE9B,6BAA6B;IA8E3C,OAAO,CAAC,mCAAmC;YAI7B,0BAA0B;IAaxC,OAAO,CAAC,8BAA8B;IAiBtC,OAAO,CAAC,4BAA4B;IA6IpC,OAAO,CAAC,6BAA6B;IAcrC,OAAO,CAAC,qCAAqC;IAyB7C,OAAO,CAAC,kCAAkC;IAgB1C,OAAO,CAAC,8CAA8C;YAIxC,uCAAuC;YA2NvC,gCAAgC;YAehC,yBAAyB;IASvC,OAAO,CAAC,2BAA2B;YAMrB,8BAA8B;IAQ5C,OAAO,CAAC,0BAA0B;YAkBpB,mCAAmC;YAWnC,qCAAqC;YAmDrC,yBAAyB;YAgGzB,8BAA8B;IAU5C,OAAO,CAAC,kCAAkC;YAQ5B,cAAc;YAuCd,6BAA6B;YAW7B,0BAA0B;YAoB1B,6BAA6B;YA4E7B,gBAAgB;IAiB9B,OAAO,CAAC,qBAAqB;CAM9B"}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { BaseMethod } from '../BaseMethod';
|
|
2
|
-
import { type Pro2WallpaperColorFormat
|
|
2
|
+
import { type Pro2WallpaperColorFormat } from '../../utils/pro2Wallpaper';
|
|
3
3
|
export type DeviceUploadWallpaperParams = {
|
|
4
4
|
jpegBase64: string;
|
|
5
5
|
fileName?: string;
|
|
6
6
|
chunkSize?: number;
|
|
7
|
-
encoding?: Pro2WallpaperEncoding;
|
|
8
7
|
};
|
|
9
8
|
export type DeviceUploadWallpaperResponse = {
|
|
10
9
|
path: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DeviceUploadWallpaper.d.ts","sourceRoot":"","sources":["../../../src/api/protocol-v2/DeviceUploadWallpaper.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"DeviceUploadWallpaper.d.ts","sourceRoot":"","sources":["../../../src/api/protocol-v2/DeviceUploadWallpaper.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAO3C,OAAO,EAGL,KAAK,wBAAwB,EAE9B,MAAM,2BAA2B,CAAC;AAEnC,MAAM,MAAM,2BAA2B,GAAG;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,wBAAwB,CAAC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAmBF,MAAM,CAAC,OAAO,OAAO,qBAAsB,SAAQ,UAAU,CAAC,2BAA2B,CAAC;IACxF,qBAAqB;IAIrB,OAAO,CAAC,OAAO,CAAC,CAA8D;IAE9E,OAAO,CAAC,cAAc,CAAS;IAE/B,OAAO,CAAC,QAAQ,CAAS;IAEzB,OAAO,CAAC,IAAI,CAAM;IAElB,IAAI;YA2BU,kBAAkB;YAgBlB,eAAe;YAaf,MAAM;IAwBd,GAAG,IAAI,OAAO,CAAC,6BAA6B,CAAC;CAyBpD"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1113,13 +1113,11 @@ declare const switchTransport: ({ env, Transport, plugin, }: {
|
|
|
1113
1113
|
|
|
1114
1114
|
declare const PRO2_WALLPAPER_WIDTH = 604;
|
|
1115
1115
|
declare const PRO2_WALLPAPER_HEIGHT = 1024;
|
|
1116
|
-
type Pro2WallpaperColorFormat = 'RGB565' | 'RGB565A8'
|
|
1117
|
-
type Pro2WallpaperEncoding = 'rgb565' | 'i8-lz4';
|
|
1116
|
+
type Pro2WallpaperColorFormat = 'RGB565' | 'RGB565A8';
|
|
1118
1117
|
declare function encodePro2Wallpaper(options: {
|
|
1119
1118
|
width: number;
|
|
1120
1119
|
height: number;
|
|
1121
1120
|
rgba: Uint8Array | ArrayBuffer;
|
|
1122
|
-
encoding?: Pro2WallpaperEncoding;
|
|
1123
1121
|
}): {
|
|
1124
1122
|
data: Uint8Array;
|
|
1125
1123
|
colorFormat: Pro2WallpaperColorFormat;
|
|
@@ -1129,7 +1127,6 @@ type DeviceUploadWallpaperParams = {
|
|
|
1129
1127
|
jpegBase64: string;
|
|
1130
1128
|
fileName?: string;
|
|
1131
1129
|
chunkSize?: number;
|
|
1132
|
-
encoding?: Pro2WallpaperEncoding;
|
|
1133
1130
|
};
|
|
1134
1131
|
type DeviceUploadWallpaperResponse = {
|
|
1135
1132
|
path: string;
|
package/dist/index.js
CHANGED
|
@@ -42476,18 +42476,6 @@ const PRO2_WALLPAPER_WIDTH = 604;
|
|
|
42476
42476
|
const PRO2_WALLPAPER_HEIGHT = 1024;
|
|
42477
42477
|
const COLOR_FORMAT_RGB565 = 0x12;
|
|
42478
42478
|
const COLOR_FORMAT_RGB565A8 = 0x14;
|
|
42479
|
-
const COLOR_FORMAT_I8 = 0x0a;
|
|
42480
|
-
const IMAGE_FLAG_COMPRESSED = 0x0008;
|
|
42481
|
-
const IMAGE_COMPRESSION_LZ4 = 0x00000002;
|
|
42482
|
-
const I8_PALETTE_SIZE = 256 * 4;
|
|
42483
|
-
const I8_RED_LEVELS = 6;
|
|
42484
|
-
const I8_GREEN_LEVELS = 7;
|
|
42485
|
-
const I8_BLUE_LEVELS = 6;
|
|
42486
|
-
const LZ4_MIN_MATCH = 4;
|
|
42487
|
-
const LZ4_LAST_LITERALS = 5;
|
|
42488
|
-
const LZ4_MATCH_FIND_LIMIT = 12;
|
|
42489
|
-
const LZ4_HASH_BITS = 16;
|
|
42490
|
-
const LZ4_HASH_MULTIPLIER = -1640531535;
|
|
42491
42479
|
const RED_THRESHOLD = [
|
|
42492
42480
|
1, 7, 3, 5, 0, 8, 2, 6, 7, 1, 5, 3, 8, 0, 6, 2, 3, 5, 0, 8, 2, 6, 1, 7, 5, 3, 8, 0, 6, 2, 7, 1, 0,
|
|
42493
42481
|
8, 2, 6, 1, 7, 3, 5, 8, 0, 6, 2, 7, 1, 5, 3, 2, 6, 1, 7, 3, 5, 0, 8, 6, 2, 7, 1, 5, 3, 8, 0,
|
|
@@ -42509,149 +42497,6 @@ function asBytes(rgba) {
|
|
|
42509
42497
|
function align(value, boundary) {
|
|
42510
42498
|
return Math.ceil(value / boundary) * boundary;
|
|
42511
42499
|
}
|
|
42512
|
-
function writeLz4Length(output, offset, length) {
|
|
42513
|
-
let cursor = offset;
|
|
42514
|
-
let remaining = length;
|
|
42515
|
-
while (remaining >= 0xff) {
|
|
42516
|
-
output[cursor] = 0xff;
|
|
42517
|
-
cursor += 1;
|
|
42518
|
-
remaining -= 0xff;
|
|
42519
|
-
}
|
|
42520
|
-
output[cursor] = remaining;
|
|
42521
|
-
return cursor + 1;
|
|
42522
|
-
}
|
|
42523
|
-
function readUint32LittleEndian(data, offset) {
|
|
42524
|
-
return (data[offset] | (data[offset + 1] << 8) | (data[offset + 2] << 16) | (data[offset + 3] << 24));
|
|
42525
|
-
}
|
|
42526
|
-
function getLz4Hash(sequence) {
|
|
42527
|
-
return (Math.imul(sequence, LZ4_HASH_MULTIPLIER) >>> (32 - LZ4_HASH_BITS)) & 0xffff;
|
|
42528
|
-
}
|
|
42529
|
-
function compressLz4Block(input) {
|
|
42530
|
-
const output = new Uint8Array(input.byteLength + Math.floor(input.byteLength / 0xff) + 16);
|
|
42531
|
-
const hashTable = new Int32Array(1 << LZ4_HASH_BITS);
|
|
42532
|
-
hashTable.fill(-1);
|
|
42533
|
-
let anchor = 0;
|
|
42534
|
-
let inputOffset = 0;
|
|
42535
|
-
let outputOffset = 0;
|
|
42536
|
-
const matchFindEnd = input.byteLength - LZ4_MATCH_FIND_LIMIT;
|
|
42537
|
-
const matchCopyEnd = input.byteLength - LZ4_LAST_LITERALS;
|
|
42538
|
-
while (inputOffset <= matchFindEnd) {
|
|
42539
|
-
const sequence = readUint32LittleEndian(input, inputOffset);
|
|
42540
|
-
const hash = getLz4Hash(sequence);
|
|
42541
|
-
const reference = hashTable[hash];
|
|
42542
|
-
hashTable[hash] = inputOffset;
|
|
42543
|
-
const matchOffset = inputOffset - reference;
|
|
42544
|
-
const hasMatch = reference >= 0 &&
|
|
42545
|
-
matchOffset <= 0xffff &&
|
|
42546
|
-
readUint32LittleEndian(input, reference) === sequence;
|
|
42547
|
-
if (hasMatch) {
|
|
42548
|
-
let matchLength = LZ4_MIN_MATCH;
|
|
42549
|
-
while (inputOffset + matchLength < matchCopyEnd &&
|
|
42550
|
-
input[reference + matchLength] === input[inputOffset + matchLength]) {
|
|
42551
|
-
matchLength += 1;
|
|
42552
|
-
}
|
|
42553
|
-
const literalLength = inputOffset - anchor;
|
|
42554
|
-
const encodedMatchLength = matchLength - LZ4_MIN_MATCH;
|
|
42555
|
-
const tokenOffset = outputOffset;
|
|
42556
|
-
outputOffset += 1;
|
|
42557
|
-
output[tokenOffset] =
|
|
42558
|
-
(Math.min(literalLength, 0x0f) << 4) | Math.min(encodedMatchLength, 0x0f);
|
|
42559
|
-
if (literalLength >= 0x0f) {
|
|
42560
|
-
outputOffset = writeLz4Length(output, outputOffset, literalLength - 0x0f);
|
|
42561
|
-
}
|
|
42562
|
-
output.set(input.subarray(anchor, inputOffset), outputOffset);
|
|
42563
|
-
outputOffset += literalLength;
|
|
42564
|
-
output[outputOffset] = matchOffset & 0xff;
|
|
42565
|
-
output[outputOffset + 1] = matchOffset >> 8;
|
|
42566
|
-
outputOffset += 2;
|
|
42567
|
-
if (encodedMatchLength >= 0x0f) {
|
|
42568
|
-
outputOffset = writeLz4Length(output, outputOffset, encodedMatchLength - 0x0f);
|
|
42569
|
-
}
|
|
42570
|
-
const matchStart = inputOffset;
|
|
42571
|
-
inputOffset += matchLength;
|
|
42572
|
-
anchor = inputOffset;
|
|
42573
|
-
for (let cursor = Math.max(matchStart + 1, inputOffset - 2); cursor < inputOffset; cursor += 1) {
|
|
42574
|
-
if (cursor <= matchFindEnd) {
|
|
42575
|
-
hashTable[getLz4Hash(readUint32LittleEndian(input, cursor))] = cursor;
|
|
42576
|
-
}
|
|
42577
|
-
}
|
|
42578
|
-
}
|
|
42579
|
-
else {
|
|
42580
|
-
inputOffset += 1;
|
|
42581
|
-
}
|
|
42582
|
-
}
|
|
42583
|
-
const literalLength = input.byteLength - anchor;
|
|
42584
|
-
const tokenOffset = outputOffset;
|
|
42585
|
-
outputOffset += 1;
|
|
42586
|
-
output[tokenOffset] = Math.min(literalLength, 0x0f) << 4;
|
|
42587
|
-
if (literalLength >= 0x0f) {
|
|
42588
|
-
outputOffset = writeLz4Length(output, outputOffset, literalLength - 0x0f);
|
|
42589
|
-
}
|
|
42590
|
-
output.set(input.subarray(anchor), outputOffset);
|
|
42591
|
-
outputOffset += literalLength;
|
|
42592
|
-
return output.slice(0, outputOffset);
|
|
42593
|
-
}
|
|
42594
|
-
function quantizeChannel(value, levels) {
|
|
42595
|
-
return Math.floor((value * (levels - 1) + 0x7f) / 0xff);
|
|
42596
|
-
}
|
|
42597
|
-
function expandChannel(value, levels) {
|
|
42598
|
-
return Math.floor((value * 0xff + Math.floor((levels - 1) / 2)) / (levels - 1));
|
|
42599
|
-
}
|
|
42600
|
-
function encodePro2I8Lz4(options) {
|
|
42601
|
-
const { width, height } = options;
|
|
42602
|
-
if (!Number.isInteger(width) || width <= 0 || width > 0xffff) {
|
|
42603
|
-
throw invalidParameter$2('Wallpaper width must be an integer between 1 and 65535.');
|
|
42604
|
-
}
|
|
42605
|
-
if (!Number.isInteger(height) || height <= 0 || height > 0xffff) {
|
|
42606
|
-
throw invalidParameter$2('Wallpaper height must be an integer between 1 and 65535.');
|
|
42607
|
-
}
|
|
42608
|
-
const rgba = asBytes(options.rgba);
|
|
42609
|
-
const expectedLength = width * height * 4;
|
|
42610
|
-
if (rgba.byteLength !== expectedLength) {
|
|
42611
|
-
throw invalidParameter$2(`Wallpaper RGBA data length must be ${expectedLength} bytes, received ${rgba.byteLength}.`);
|
|
42612
|
-
}
|
|
42613
|
-
const stride = width;
|
|
42614
|
-
const rawData = new Uint8Array(I8_PALETTE_SIZE + stride * height);
|
|
42615
|
-
for (let red = 0; red < I8_RED_LEVELS; red += 1) {
|
|
42616
|
-
for (let green = 0; green < I8_GREEN_LEVELS; green += 1) {
|
|
42617
|
-
for (let blue = 0; blue < I8_BLUE_LEVELS; blue += 1) {
|
|
42618
|
-
const paletteIndex = (red * I8_GREEN_LEVELS + green) * I8_BLUE_LEVELS + blue;
|
|
42619
|
-
const paletteOffset = paletteIndex * 4;
|
|
42620
|
-
rawData[paletteOffset] = expandChannel(blue, I8_BLUE_LEVELS);
|
|
42621
|
-
rawData[paletteOffset + 1] = expandChannel(green, I8_GREEN_LEVELS);
|
|
42622
|
-
rawData[paletteOffset + 2] = expandChannel(red, I8_RED_LEVELS);
|
|
42623
|
-
rawData[paletteOffset + 3] = 0xff;
|
|
42624
|
-
}
|
|
42625
|
-
}
|
|
42626
|
-
}
|
|
42627
|
-
for (let pixel = 0; pixel < width * height; pixel += 1) {
|
|
42628
|
-
const sourceOffset = pixel * 4;
|
|
42629
|
-
const alpha = rgba[sourceOffset + 3];
|
|
42630
|
-
const red = Math.round((rgba[sourceOffset] * alpha) / 0xff);
|
|
42631
|
-
const green = Math.round((rgba[sourceOffset + 1] * alpha) / 0xff);
|
|
42632
|
-
const blue = Math.round((rgba[sourceOffset + 2] * alpha) / 0xff);
|
|
42633
|
-
const paletteIndex = (quantizeChannel(red, I8_RED_LEVELS) * I8_GREEN_LEVELS +
|
|
42634
|
-
quantizeChannel(green, I8_GREEN_LEVELS)) *
|
|
42635
|
-
I8_BLUE_LEVELS +
|
|
42636
|
-
quantizeChannel(blue, I8_BLUE_LEVELS);
|
|
42637
|
-
rawData[I8_PALETTE_SIZE + pixel] = paletteIndex;
|
|
42638
|
-
}
|
|
42639
|
-
const compressed = compressLz4Block(rawData);
|
|
42640
|
-
const data = new Uint8Array(24 + compressed.byteLength);
|
|
42641
|
-
const view = new DataView(data.buffer);
|
|
42642
|
-
data[0] = 0x19;
|
|
42643
|
-
data[1] = COLOR_FORMAT_I8;
|
|
42644
|
-
view.setUint16(2, IMAGE_FLAG_COMPRESSED, true);
|
|
42645
|
-
view.setUint16(4, width, true);
|
|
42646
|
-
view.setUint16(6, height, true);
|
|
42647
|
-
view.setUint16(8, stride, true);
|
|
42648
|
-
view.setUint16(10, 0, true);
|
|
42649
|
-
view.setUint32(12, IMAGE_COMPRESSION_LZ4, true);
|
|
42650
|
-
view.setUint32(16, compressed.byteLength, true);
|
|
42651
|
-
view.setUint32(20, rawData.byteLength, true);
|
|
42652
|
-
data.set(compressed, 24);
|
|
42653
|
-
return { data, colorFormat: 'I8' };
|
|
42654
|
-
}
|
|
42655
42500
|
function encodePro2Image(options) {
|
|
42656
42501
|
var _a;
|
|
42657
42502
|
const { width, height } = options;
|
|
@@ -42719,9 +42564,6 @@ function encodePro2Image(options) {
|
|
|
42719
42564
|
return { data, colorFormat };
|
|
42720
42565
|
}
|
|
42721
42566
|
function encodePro2Wallpaper(options) {
|
|
42722
|
-
if (options.encoding === 'i8-lz4') {
|
|
42723
|
-
return encodePro2I8Lz4(options);
|
|
42724
|
-
}
|
|
42725
42567
|
return encodePro2Image(options);
|
|
42726
42568
|
}
|
|
42727
42569
|
|
|
@@ -53483,7 +53325,11 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
53483
53325
|
}
|
|
53484
53326
|
seenTargetIds.add(targetId);
|
|
53485
53327
|
}
|
|
53486
|
-
const completedTargets = matchingTargets.filter(target =>
|
|
53328
|
+
const completedTargets = matchingTargets.filter(target => {
|
|
53329
|
+
const targetId = normalizeProtocolV2TargetId(target.target_id);
|
|
53330
|
+
return (isProtocolV2TargetStatusFinished(target.status) &&
|
|
53331
|
+
(!liveTargetIds || (targetId !== undefined && liveTargetIds.has(targetId))));
|
|
53332
|
+
});
|
|
53487
53333
|
const completedTargetIds = new Set();
|
|
53488
53334
|
completedTargets.forEach(target => {
|
|
53489
53335
|
const targetId = normalizeProtocolV2TargetId(target.target_id);
|
|
@@ -53592,20 +53438,17 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
53592
53438
|
}
|
|
53593
53439
|
const currentDeviceInfo = deviceInfo;
|
|
53594
53440
|
try {
|
|
53595
|
-
const statusResponse = yield this.device.getCommands().typedCall('DeviceFirmwareUpdateStatusGet',
|
|
53441
|
+
const statusResponse = yield this.device.getCommands().typedCall('DeviceFirmwareUpdateStatusGet', 'DeviceFirmwareUpdateStatus', {
|
|
53596
53442
|
fields: {
|
|
53597
53443
|
status: true,
|
|
53598
53444
|
payload_version: true,
|
|
53599
53445
|
path: true,
|
|
53600
53446
|
},
|
|
53601
53447
|
}, { timeoutMs: PROTOCOL_V2_FIRMWARE_STATUS_RESPONSE_TIMEOUT });
|
|
53602
|
-
if (
|
|
53448
|
+
if (this.protocolV2InstallRequestConfirmed) {
|
|
53603
53449
|
installEvidenceObserved = true;
|
|
53604
|
-
lastError = new Error('Protocol V2 firmware install acknowledged; waiting for target status');
|
|
53605
53450
|
}
|
|
53606
|
-
const statusTargets = statusResponse.
|
|
53607
|
-
? ((_a = statusResponse.message.records) !== null && _a !== void 0 ? _a : [])
|
|
53608
|
-
: [];
|
|
53451
|
+
const statusTargets = ((_a = statusResponse.message.records) !== null && _a !== void 0 ? _a : []);
|
|
53609
53452
|
this.collectProtocolV2LiveTargetIds(statusTargets, expectedTargetIds, liveTargetIds);
|
|
53610
53453
|
if (liveTargetIds.size > 0) {
|
|
53611
53454
|
currentInstallStatusObserved = true;
|
|
@@ -53644,9 +53487,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
53644
53487
|
}
|
|
53645
53488
|
}
|
|
53646
53489
|
if (statusTargets.length === 0) {
|
|
53647
|
-
|
|
53648
|
-
lastError = new Error('Protocol V2 firmware update is waiting for user confirmation or target status');
|
|
53649
|
-
}
|
|
53490
|
+
lastError = new Error('Protocol V2 firmware update is waiting for user confirmation or target status');
|
|
53650
53491
|
}
|
|
53651
53492
|
else {
|
|
53652
53493
|
const missingTargetIds = this.getProtocolV2MissingTargetIds(statusTargets, expectedTargetIds);
|
|
@@ -53941,7 +53782,6 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
53941
53782
|
});
|
|
53942
53783
|
}
|
|
53943
53784
|
acquireProtocolV2BleDevice(skipProtocolProbe = false) {
|
|
53944
|
-
var _a;
|
|
53945
53785
|
return __awaiter(this, void 0, void 0, function* () {
|
|
53946
53786
|
const connector = this.device.deviceConnector;
|
|
53947
53787
|
const expectedId = this.device.originalDescriptor.id;
|
|
@@ -53949,14 +53789,9 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
53949
53789
|
yield (connector === null || connector === void 0 ? void 0 : connector.acquire(expectedId, null, true, PROTOCOL_V2_CONNECT_PROTOCOL));
|
|
53950
53790
|
return;
|
|
53951
53791
|
}
|
|
53952
|
-
|
|
53953
|
-
const reconnectDescriptor = (_a = deviceDiff === null || deviceDiff === void 0 ? void 0 : deviceDiff.descriptors) === null || _a === void 0 ? void 0 : _a.find(descriptor => descriptor.id === expectedId);
|
|
53954
|
-
if (!reconnectDescriptor) {
|
|
53955
|
-
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceNotFound);
|
|
53956
|
-
}
|
|
53957
|
-
yield (connector === null || connector === void 0 ? void 0 : connector.acquire(reconnectDescriptor.id, null, true, PROTOCOL_V2_CONNECT_PROTOCOL, undefined, undefined, skipProtocolProbe));
|
|
53792
|
+
yield (connector === null || connector === void 0 ? void 0 : connector.acquire(expectedId, null, true, PROTOCOL_V2_CONNECT_PROTOCOL, undefined, undefined, skipProtocolProbe));
|
|
53958
53793
|
this.device.commands.disposed = false;
|
|
53959
|
-
this.device.getCommands().mainId =
|
|
53794
|
+
this.device.getCommands().mainId = expectedId;
|
|
53960
53795
|
});
|
|
53961
53796
|
}
|
|
53962
53797
|
protocolV2StartFirmwareUpdate({ targets, }) {
|
|
@@ -53969,6 +53804,32 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
53969
53804
|
this.device.setCancelableAction(() => commands.cancelDevice());
|
|
53970
53805
|
const interaction = this.device.createProtocolV2UiPhaseMetadata('button', 'start');
|
|
53971
53806
|
this.postMessage(createUiMessage(UI_REQUEST.REQUEST_BUTTON, Object.assign({ device: this.device.toMessageObject(), source: 'method-lifecycle', reason: 'firmware-update', completion: 'operation-completed', deviceOnly: true, operation: this.name }, (interaction ? { interaction } : {}))));
|
|
53807
|
+
if (this.isBleReconnect()) {
|
|
53808
|
+
try {
|
|
53809
|
+
yield commands.call('DeviceFirmwareUpdateRequest', {}, {
|
|
53810
|
+
returnAfterWrite: true,
|
|
53811
|
+
expectedTypes: ['Success'],
|
|
53812
|
+
onResponseAfterWrite: response => {
|
|
53813
|
+
if (response.type !== 'Success')
|
|
53814
|
+
return;
|
|
53815
|
+
this.protocolV2InstallRequestConfirmed = true;
|
|
53816
|
+
this.device.clearCancelableAction();
|
|
53817
|
+
this.postProgressMessage(1, 'installingFirmware');
|
|
53818
|
+
Log$7.log('[FirmwareUpdateV4] BLE firmware install confirmed by device response');
|
|
53819
|
+
},
|
|
53820
|
+
});
|
|
53821
|
+
Log$7.log('[FirmwareUpdateV4] BLE firmware install request written; continue with status polling');
|
|
53822
|
+
}
|
|
53823
|
+
catch (error) {
|
|
53824
|
+
this.throwIfAborted();
|
|
53825
|
+
if (!isProtocolV2DeviceDisconnectedError(error)) {
|
|
53826
|
+
throw error;
|
|
53827
|
+
}
|
|
53828
|
+
Log$7.log('[FirmwareUpdateV4] BLE transport released while writing install request; continue status polling');
|
|
53829
|
+
this.protocolV2InstallNeedsBleReconnect = true;
|
|
53830
|
+
}
|
|
53831
|
+
return;
|
|
53832
|
+
}
|
|
53972
53833
|
try {
|
|
53973
53834
|
yield commands.typedCall('DeviceFirmwareUpdateRequest', 'Success', {});
|
|
53974
53835
|
this.protocolV2InstallRequestConfirmed = true;
|
|
@@ -54472,15 +54333,10 @@ class DeviceUploadWallpaper extends BaseMethod {
|
|
|
54472
54333
|
return ['V2'];
|
|
54473
54334
|
}
|
|
54474
54335
|
init() {
|
|
54475
|
-
const { jpegBase64, fileName, chunkSize
|
|
54336
|
+
const { jpegBase64, fileName, chunkSize } = this.payload;
|
|
54476
54337
|
if (chunkSize !== undefined && (!Number.isInteger(chunkSize) || chunkSize <= 0)) {
|
|
54477
54338
|
throw invalidParameter$1('Parameter [chunkSize] must be a positive integer.');
|
|
54478
54339
|
}
|
|
54479
|
-
if (encoding !== undefined && encoding !== 'rgb565' && encoding !== 'i8-lz4') {
|
|
54480
|
-
throw invalidParameter$1('Parameter [encoding] must be either rgb565 or i8-lz4.');
|
|
54481
|
-
}
|
|
54482
|
-
const env = DataManager.getSettings('env');
|
|
54483
|
-
const resolvedEncoding = encoding !== null && encoding !== void 0 ? encoding : (env && DataManager.isBleConnect(env) ? 'i8-lz4' : 'rgb565');
|
|
54484
54340
|
const decoded = decodeJpegBase64ToRgba({
|
|
54485
54341
|
jpegBase64,
|
|
54486
54342
|
parameterName: 'jpegBase64',
|
|
@@ -54491,10 +54347,9 @@ class DeviceUploadWallpaper extends BaseMethod {
|
|
|
54491
54347
|
width: PRO2_WALLPAPER_WIDTH,
|
|
54492
54348
|
height: PRO2_WALLPAPER_HEIGHT,
|
|
54493
54349
|
rgba: decoded.data,
|
|
54494
|
-
encoding: resolvedEncoding,
|
|
54495
54350
|
});
|
|
54496
54351
|
this.path = `${WALLPAPER_DIRECTORY}/${normalizeFileName(fileName, this.encoded.data)}`;
|
|
54497
|
-
this.params = { jpegBase64, fileName, chunkSize
|
|
54352
|
+
this.params = { jpegBase64, fileName, chunkSize };
|
|
54498
54353
|
this.unlockPolicy = 'unlock-before-run';
|
|
54499
54354
|
this.protocolV2PreUnlockPinType = hdTransport.DeviceSessionPinType.Any;
|
|
54500
54355
|
this.skipForceUpdateCheck = true;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export declare const PRO2_WALLPAPER_WIDTH = 604;
|
|
2
2
|
export declare const PRO2_WALLPAPER_HEIGHT = 1024;
|
|
3
|
-
export type Pro2WallpaperColorFormat = 'RGB565' | 'RGB565A8'
|
|
4
|
-
export type Pro2WallpaperEncoding = 'rgb565' | 'i8-lz4';
|
|
3
|
+
export type Pro2WallpaperColorFormat = 'RGB565' | 'RGB565A8';
|
|
5
4
|
export type Pro2ImageAlphaMode = 'preserve' | 'black-background';
|
|
6
5
|
export declare function encodePro2Image(options: {
|
|
7
6
|
width: number;
|
|
@@ -16,7 +15,6 @@ export declare function encodePro2Wallpaper(options: {
|
|
|
16
15
|
width: number;
|
|
17
16
|
height: number;
|
|
18
17
|
rgba: Uint8Array | ArrayBuffer;
|
|
19
|
-
encoding?: Pro2WallpaperEncoding;
|
|
20
18
|
}): {
|
|
21
19
|
data: Uint8Array;
|
|
22
20
|
colorFormat: Pro2WallpaperColorFormat;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pro2Wallpaper.d.ts","sourceRoot":"","sources":["../../src/utils/pro2Wallpaper.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,oBAAoB,MAAM,CAAC;AACxC,eAAO,MAAM,qBAAqB,OAAO,CAAC;AAE1C,MAAM,MAAM,wBAAwB,GAAG,QAAQ,GAAG,UAAU,
|
|
1
|
+
{"version":3,"file":"pro2Wallpaper.d.ts","sourceRoot":"","sources":["../../src/utils/pro2Wallpaper.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,oBAAoB,MAAM,CAAC;AACxC,eAAO,MAAM,qBAAqB,OAAO,CAAC;AAE1C,MAAM,MAAM,wBAAwB,GAAG,QAAQ,GAAG,UAAU,CAAC;AAE7D,MAAM,MAAM,kBAAkB,GAAG,UAAU,GAAG,kBAAkB,CAAC;AA8BjE,wBAAgB,eAAe,CAAC,OAAO,EAAE;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,UAAU,GAAG,WAAW,CAAC;IAC/B,SAAS,CAAC,EAAE,kBAAkB,CAAC;CAChC,GAAG;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,WAAW,EAAE,wBAAwB,CAAA;CAAE,CA4E9D;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,UAAU,GAAG,WAAW,CAAC;CAChC,GAAG;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,WAAW,EAAE,wBAAwB,CAAA;CAAE,CAE9D"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/hd-core",
|
|
3
|
-
"version": "1.2.0-alpha.
|
|
3
|
+
"version": "1.2.0-alpha.172",
|
|
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.0-alpha.
|
|
29
|
-
"@onekeyfe/hd-transport": "1.2.0-alpha.
|
|
28
|
+
"@onekeyfe/hd-shared": "1.2.0-alpha.172",
|
|
29
|
+
"@onekeyfe/hd-transport": "1.2.0-alpha.172",
|
|
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": "4c6c4a4fcc52bcdd0b3ec9c36454b2074fa17a8c"
|
|
50
50
|
}
|
|
@@ -2316,9 +2316,13 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2316
2316
|
}
|
|
2317
2317
|
seenTargetIds.add(targetId);
|
|
2318
2318
|
}
|
|
2319
|
-
const completedTargets = matchingTargets.filter(target =>
|
|
2320
|
-
|
|
2321
|
-
|
|
2319
|
+
const completedTargets = matchingTargets.filter(target => {
|
|
2320
|
+
const targetId = normalizeProtocolV2TargetId(target.target_id);
|
|
2321
|
+
return (
|
|
2322
|
+
isProtocolV2TargetStatusFinished(target.status) &&
|
|
2323
|
+
(!liveTargetIds || (targetId !== undefined && liveTargetIds.has(targetId)))
|
|
2324
|
+
);
|
|
2325
|
+
});
|
|
2322
2326
|
const completedTargetIds = new Set<number>();
|
|
2323
2327
|
completedTargets.forEach(target => {
|
|
2324
2328
|
const targetId = normalizeProtocolV2TargetId(target.target_id);
|
|
@@ -2465,7 +2469,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2465
2469
|
try {
|
|
2466
2470
|
const statusResponse = await this.device.getCommands().typedCall(
|
|
2467
2471
|
'DeviceFirmwareUpdateStatusGet',
|
|
2468
|
-
|
|
2472
|
+
'DeviceFirmwareUpdateStatus',
|
|
2469
2473
|
{
|
|
2470
2474
|
fields: {
|
|
2471
2475
|
status: true,
|
|
@@ -2475,16 +2479,11 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2475
2479
|
},
|
|
2476
2480
|
{ timeoutMs: PROTOCOL_V2_FIRMWARE_STATUS_RESPONSE_TIMEOUT }
|
|
2477
2481
|
);
|
|
2478
|
-
if (
|
|
2482
|
+
if (this.protocolV2InstallRequestConfirmed) {
|
|
2479
2483
|
installEvidenceObserved = true;
|
|
2480
|
-
lastError = new Error(
|
|
2481
|
-
'Protocol V2 firmware install acknowledged; waiting for target status'
|
|
2482
|
-
);
|
|
2483
2484
|
}
|
|
2484
|
-
const statusTargets =
|
|
2485
|
-
|
|
2486
|
-
? ((statusResponse.message.records ?? []) as ProtocolV2FirmwareUpdateStatusTarget[])
|
|
2487
|
-
: [];
|
|
2485
|
+
const statusTargets = (statusResponse.message.records ??
|
|
2486
|
+
[]) as ProtocolV2FirmwareUpdateStatusTarget[];
|
|
2488
2487
|
this.collectProtocolV2LiveTargetIds(statusTargets, expectedTargetIds, liveTargetIds);
|
|
2489
2488
|
if (liveTargetIds.size > 0) {
|
|
2490
2489
|
currentInstallStatusObserved = true;
|
|
@@ -2544,11 +2543,9 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2544
2543
|
}
|
|
2545
2544
|
|
|
2546
2545
|
if (statusTargets.length === 0) {
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
);
|
|
2551
|
-
}
|
|
2546
|
+
lastError = new Error(
|
|
2547
|
+
'Protocol V2 firmware update is waiting for user confirmation or target status'
|
|
2548
|
+
);
|
|
2552
2549
|
} else {
|
|
2553
2550
|
const missingTargetIds = this.getProtocolV2MissingTargetIds(
|
|
2554
2551
|
statusTargets,
|
|
@@ -2944,15 +2941,8 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2944
2941
|
await connector?.acquire(expectedId, null, true, PROTOCOL_V2_CONNECT_PROTOCOL);
|
|
2945
2942
|
return;
|
|
2946
2943
|
}
|
|
2947
|
-
const deviceDiff = await connector?.enumerate();
|
|
2948
|
-
const reconnectDescriptor = deviceDiff?.descriptors?.find(
|
|
2949
|
-
descriptor => descriptor.id === expectedId
|
|
2950
|
-
);
|
|
2951
|
-
if (!reconnectDescriptor) {
|
|
2952
|
-
throw ERRORS.TypedError(HardwareErrorCode.DeviceNotFound);
|
|
2953
|
-
}
|
|
2954
2944
|
await connector?.acquire(
|
|
2955
|
-
|
|
2945
|
+
expectedId,
|
|
2956
2946
|
null,
|
|
2957
2947
|
true,
|
|
2958
2948
|
PROTOCOL_V2_CONNECT_PROTOCOL,
|
|
@@ -2961,7 +2951,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2961
2951
|
skipProtocolProbe
|
|
2962
2952
|
);
|
|
2963
2953
|
this.device.commands.disposed = false;
|
|
2964
|
-
this.device.getCommands().mainId =
|
|
2954
|
+
this.device.getCommands().mainId = expectedId;
|
|
2965
2955
|
}
|
|
2966
2956
|
|
|
2967
2957
|
private async protocolV2StartFirmwareUpdate({
|
|
@@ -2987,6 +2977,40 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2987
2977
|
...(interaction ? { interaction } : {}),
|
|
2988
2978
|
})
|
|
2989
2979
|
);
|
|
2980
|
+
|
|
2981
|
+
if (this.isBleReconnect()) {
|
|
2982
|
+
try {
|
|
2983
|
+
await commands.call(
|
|
2984
|
+
'DeviceFirmwareUpdateRequest',
|
|
2985
|
+
{},
|
|
2986
|
+
{
|
|
2987
|
+
returnAfterWrite: true,
|
|
2988
|
+
expectedTypes: ['Success'],
|
|
2989
|
+
onResponseAfterWrite: response => {
|
|
2990
|
+
if (response.type !== 'Success') return;
|
|
2991
|
+
this.protocolV2InstallRequestConfirmed = true;
|
|
2992
|
+
this.device.clearCancelableAction();
|
|
2993
|
+
this.postProgressMessage(1, 'installingFirmware');
|
|
2994
|
+
Log.log('[FirmwareUpdateV4] BLE firmware install confirmed by device response');
|
|
2995
|
+
},
|
|
2996
|
+
}
|
|
2997
|
+
);
|
|
2998
|
+
Log.log(
|
|
2999
|
+
'[FirmwareUpdateV4] BLE firmware install request written; continue with status polling'
|
|
3000
|
+
);
|
|
3001
|
+
} catch (error) {
|
|
3002
|
+
this.throwIfAborted();
|
|
3003
|
+
if (!isProtocolV2DeviceDisconnectedError(error)) {
|
|
3004
|
+
throw error;
|
|
3005
|
+
}
|
|
3006
|
+
Log.log(
|
|
3007
|
+
'[FirmwareUpdateV4] BLE transport released while writing install request; continue status polling'
|
|
3008
|
+
);
|
|
3009
|
+
this.protocolV2InstallNeedsBleReconnect = true;
|
|
3010
|
+
}
|
|
3011
|
+
return;
|
|
3012
|
+
}
|
|
3013
|
+
|
|
2990
3014
|
try {
|
|
2991
3015
|
await commands.typedCall('DeviceFirmwareUpdateRequest', 'Success', {});
|
|
2992
3016
|
this.protocolV2InstallRequestConfirmed = true;
|
|
@@ -7,7 +7,6 @@ import { BaseMethod } from '../BaseMethod';
|
|
|
7
7
|
import { decodeJpegBase64ToRgba } from '../helpers/base64Data';
|
|
8
8
|
import { invalidParameter } from '../helpers/filesystemValidation';
|
|
9
9
|
import { writeProtocolV2File } from '../helpers/protocolV2FileWrite';
|
|
10
|
-
import { DataManager } from '../../data-manager';
|
|
11
10
|
import { UI_REQUEST, createUiMessage } from '../../events/ui-request';
|
|
12
11
|
import { supportsProtocolV2Message } from '../../protocols/protocol-v2/features';
|
|
13
12
|
import { LoggerNames, getLogger } from '../../utils';
|
|
@@ -15,7 +14,6 @@ import {
|
|
|
15
14
|
PRO2_WALLPAPER_HEIGHT,
|
|
16
15
|
PRO2_WALLPAPER_WIDTH,
|
|
17
16
|
type Pro2WallpaperColorFormat,
|
|
18
|
-
type Pro2WallpaperEncoding,
|
|
19
17
|
encodePro2Wallpaper,
|
|
20
18
|
} from '../../utils/pro2Wallpaper';
|
|
21
19
|
|
|
@@ -23,7 +21,6 @@ export type DeviceUploadWallpaperParams = {
|
|
|
23
21
|
jpegBase64: string;
|
|
24
22
|
fileName?: string;
|
|
25
23
|
chunkSize?: number;
|
|
26
|
-
encoding?: Pro2WallpaperEncoding;
|
|
27
24
|
};
|
|
28
25
|
|
|
29
26
|
export type DeviceUploadWallpaperResponse = {
|
|
@@ -64,16 +61,10 @@ export default class DeviceUploadWallpaper extends BaseMethod<DeviceUploadWallpa
|
|
|
64
61
|
private path = '';
|
|
65
62
|
|
|
66
63
|
init() {
|
|
67
|
-
const { jpegBase64, fileName, chunkSize
|
|
64
|
+
const { jpegBase64, fileName, chunkSize } = this.payload;
|
|
68
65
|
if (chunkSize !== undefined && (!Number.isInteger(chunkSize) || chunkSize <= 0)) {
|
|
69
66
|
throw invalidParameter('Parameter [chunkSize] must be a positive integer.');
|
|
70
67
|
}
|
|
71
|
-
if (encoding !== undefined && encoding !== 'rgb565' && encoding !== 'i8-lz4') {
|
|
72
|
-
throw invalidParameter('Parameter [encoding] must be either rgb565 or i8-lz4.');
|
|
73
|
-
}
|
|
74
|
-
const env = DataManager.getSettings('env');
|
|
75
|
-
const resolvedEncoding: Pro2WallpaperEncoding =
|
|
76
|
-
encoding ?? (env && DataManager.isBleConnect(env) ? 'i8-lz4' : 'rgb565');
|
|
77
68
|
|
|
78
69
|
const decoded = decodeJpegBase64ToRgba({
|
|
79
70
|
jpegBase64,
|
|
@@ -85,10 +76,9 @@ export default class DeviceUploadWallpaper extends BaseMethod<DeviceUploadWallpa
|
|
|
85
76
|
width: PRO2_WALLPAPER_WIDTH,
|
|
86
77
|
height: PRO2_WALLPAPER_HEIGHT,
|
|
87
78
|
rgba: decoded.data,
|
|
88
|
-
encoding: resolvedEncoding,
|
|
89
79
|
});
|
|
90
80
|
this.path = `${WALLPAPER_DIRECTORY}/${normalizeFileName(fileName, this.encoded.data)}`;
|
|
91
|
-
this.params = { jpegBase64, fileName, chunkSize
|
|
81
|
+
this.params = { jpegBase64, fileName, chunkSize };
|
|
92
82
|
this.unlockPolicy = 'unlock-before-run';
|
|
93
83
|
// File writes and wallpaper apply require an unlocked device. Either PIN
|
|
94
84
|
// may authorize this device-management action.
|
|
@@ -6,26 +6,12 @@ import { ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
|
|
|
6
6
|
export const PRO2_WALLPAPER_WIDTH = 604;
|
|
7
7
|
export const PRO2_WALLPAPER_HEIGHT = 1024;
|
|
8
8
|
|
|
9
|
-
export type Pro2WallpaperColorFormat = 'RGB565' | 'RGB565A8'
|
|
10
|
-
|
|
11
|
-
export type Pro2WallpaperEncoding = 'rgb565' | 'i8-lz4';
|
|
9
|
+
export type Pro2WallpaperColorFormat = 'RGB565' | 'RGB565A8';
|
|
12
10
|
|
|
13
11
|
export type Pro2ImageAlphaMode = 'preserve' | 'black-background';
|
|
14
12
|
|
|
15
13
|
const COLOR_FORMAT_RGB565 = 0x12;
|
|
16
14
|
const COLOR_FORMAT_RGB565A8 = 0x14;
|
|
17
|
-
const COLOR_FORMAT_I8 = 0x0a;
|
|
18
|
-
const IMAGE_FLAG_COMPRESSED = 0x0008;
|
|
19
|
-
const IMAGE_COMPRESSION_LZ4 = 0x00000002;
|
|
20
|
-
const I8_PALETTE_SIZE = 256 * 4;
|
|
21
|
-
const I8_RED_LEVELS = 6;
|
|
22
|
-
const I8_GREEN_LEVELS = 7;
|
|
23
|
-
const I8_BLUE_LEVELS = 6;
|
|
24
|
-
const LZ4_MIN_MATCH = 4;
|
|
25
|
-
const LZ4_LAST_LITERALS = 5;
|
|
26
|
-
const LZ4_MATCH_FIND_LIMIT = 12;
|
|
27
|
-
const LZ4_HASH_BITS = 16;
|
|
28
|
-
const LZ4_HASH_MULTIPLIER = -1640531535;
|
|
29
15
|
|
|
30
16
|
const RED_THRESHOLD = [
|
|
31
17
|
1, 7, 3, 5, 0, 8, 2, 6, 7, 1, 5, 3, 8, 0, 6, 2, 3, 5, 0, 8, 2, 6, 1, 7, 5, 3, 8, 0, 6, 2, 7, 1, 0,
|
|
@@ -52,184 +38,6 @@ function align(value: number, boundary: number): number {
|
|
|
52
38
|
return Math.ceil(value / boundary) * boundary;
|
|
53
39
|
}
|
|
54
40
|
|
|
55
|
-
function writeLz4Length(output: Uint8Array, offset: number, length: number) {
|
|
56
|
-
let cursor = offset;
|
|
57
|
-
let remaining = length;
|
|
58
|
-
while (remaining >= 0xff) {
|
|
59
|
-
output[cursor] = 0xff;
|
|
60
|
-
cursor += 1;
|
|
61
|
-
remaining -= 0xff;
|
|
62
|
-
}
|
|
63
|
-
output[cursor] = remaining;
|
|
64
|
-
return cursor + 1;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function readUint32LittleEndian(data: Uint8Array, offset: number) {
|
|
68
|
-
return (
|
|
69
|
-
data[offset] | (data[offset + 1] << 8) | (data[offset + 2] << 16) | (data[offset + 3] << 24)
|
|
70
|
-
);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function getLz4Hash(sequence: number) {
|
|
74
|
-
return (Math.imul(sequence, LZ4_HASH_MULTIPLIER) >>> (32 - LZ4_HASH_BITS)) & 0xffff;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function compressLz4Block(input: Uint8Array) {
|
|
78
|
-
const output = new Uint8Array(input.byteLength + Math.floor(input.byteLength / 0xff) + 16);
|
|
79
|
-
const hashTable = new Int32Array(1 << LZ4_HASH_BITS);
|
|
80
|
-
hashTable.fill(-1);
|
|
81
|
-
|
|
82
|
-
let anchor = 0;
|
|
83
|
-
let inputOffset = 0;
|
|
84
|
-
let outputOffset = 0;
|
|
85
|
-
const matchFindEnd = input.byteLength - LZ4_MATCH_FIND_LIMIT;
|
|
86
|
-
const matchCopyEnd = input.byteLength - LZ4_LAST_LITERALS;
|
|
87
|
-
|
|
88
|
-
while (inputOffset <= matchFindEnd) {
|
|
89
|
-
const sequence = readUint32LittleEndian(input, inputOffset);
|
|
90
|
-
const hash = getLz4Hash(sequence);
|
|
91
|
-
const reference = hashTable[hash];
|
|
92
|
-
hashTable[hash] = inputOffset;
|
|
93
|
-
|
|
94
|
-
const matchOffset = inputOffset - reference;
|
|
95
|
-
const hasMatch =
|
|
96
|
-
reference >= 0 &&
|
|
97
|
-
matchOffset <= 0xffff &&
|
|
98
|
-
readUint32LittleEndian(input, reference) === sequence;
|
|
99
|
-
if (hasMatch) {
|
|
100
|
-
let matchLength = LZ4_MIN_MATCH;
|
|
101
|
-
while (
|
|
102
|
-
inputOffset + matchLength < matchCopyEnd &&
|
|
103
|
-
input[reference + matchLength] === input[inputOffset + matchLength]
|
|
104
|
-
) {
|
|
105
|
-
matchLength += 1;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const literalLength = inputOffset - anchor;
|
|
109
|
-
const encodedMatchLength = matchLength - LZ4_MIN_MATCH;
|
|
110
|
-
const tokenOffset = outputOffset;
|
|
111
|
-
outputOffset += 1;
|
|
112
|
-
output[tokenOffset] =
|
|
113
|
-
(Math.min(literalLength, 0x0f) << 4) | Math.min(encodedMatchLength, 0x0f);
|
|
114
|
-
|
|
115
|
-
if (literalLength >= 0x0f) {
|
|
116
|
-
outputOffset = writeLz4Length(output, outputOffset, literalLength - 0x0f);
|
|
117
|
-
}
|
|
118
|
-
output.set(input.subarray(anchor, inputOffset), outputOffset);
|
|
119
|
-
outputOffset += literalLength;
|
|
120
|
-
|
|
121
|
-
output[outputOffset] = matchOffset & 0xff;
|
|
122
|
-
output[outputOffset + 1] = matchOffset >> 8;
|
|
123
|
-
outputOffset += 2;
|
|
124
|
-
if (encodedMatchLength >= 0x0f) {
|
|
125
|
-
outputOffset = writeLz4Length(output, outputOffset, encodedMatchLength - 0x0f);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const matchStart = inputOffset;
|
|
129
|
-
inputOffset += matchLength;
|
|
130
|
-
anchor = inputOffset;
|
|
131
|
-
for (
|
|
132
|
-
let cursor = Math.max(matchStart + 1, inputOffset - 2);
|
|
133
|
-
cursor < inputOffset;
|
|
134
|
-
cursor += 1
|
|
135
|
-
) {
|
|
136
|
-
if (cursor <= matchFindEnd) {
|
|
137
|
-
hashTable[getLz4Hash(readUint32LittleEndian(input, cursor))] = cursor;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
} else {
|
|
141
|
-
inputOffset += 1;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
const literalLength = input.byteLength - anchor;
|
|
146
|
-
const tokenOffset = outputOffset;
|
|
147
|
-
outputOffset += 1;
|
|
148
|
-
output[tokenOffset] = Math.min(literalLength, 0x0f) << 4;
|
|
149
|
-
if (literalLength >= 0x0f) {
|
|
150
|
-
outputOffset = writeLz4Length(output, outputOffset, literalLength - 0x0f);
|
|
151
|
-
}
|
|
152
|
-
output.set(input.subarray(anchor), outputOffset);
|
|
153
|
-
outputOffset += literalLength;
|
|
154
|
-
|
|
155
|
-
return output.slice(0, outputOffset);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
function quantizeChannel(value: number, levels: number) {
|
|
159
|
-
return Math.floor((value * (levels - 1) + 0x7f) / 0xff);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
function expandChannel(value: number, levels: number) {
|
|
163
|
-
return Math.floor((value * 0xff + Math.floor((levels - 1) / 2)) / (levels - 1));
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
function encodePro2I8Lz4(options: {
|
|
167
|
-
width: number;
|
|
168
|
-
height: number;
|
|
169
|
-
rgba: Uint8Array | ArrayBuffer;
|
|
170
|
-
}): { data: Uint8Array; colorFormat: Pro2WallpaperColorFormat } {
|
|
171
|
-
const { width, height } = options;
|
|
172
|
-
if (!Number.isInteger(width) || width <= 0 || width > 0xffff) {
|
|
173
|
-
throw invalidParameter('Wallpaper width must be an integer between 1 and 65535.');
|
|
174
|
-
}
|
|
175
|
-
if (!Number.isInteger(height) || height <= 0 || height > 0xffff) {
|
|
176
|
-
throw invalidParameter('Wallpaper height must be an integer between 1 and 65535.');
|
|
177
|
-
}
|
|
178
|
-
const rgba = asBytes(options.rgba);
|
|
179
|
-
const expectedLength = width * height * 4;
|
|
180
|
-
if (rgba.byteLength !== expectedLength) {
|
|
181
|
-
throw invalidParameter(
|
|
182
|
-
`Wallpaper RGBA data length must be ${expectedLength} bytes, received ${rgba.byteLength}.`
|
|
183
|
-
);
|
|
184
|
-
}
|
|
185
|
-
const stride = width;
|
|
186
|
-
const rawData = new Uint8Array(I8_PALETTE_SIZE + stride * height);
|
|
187
|
-
|
|
188
|
-
for (let red = 0; red < I8_RED_LEVELS; red += 1) {
|
|
189
|
-
for (let green = 0; green < I8_GREEN_LEVELS; green += 1) {
|
|
190
|
-
for (let blue = 0; blue < I8_BLUE_LEVELS; blue += 1) {
|
|
191
|
-
const paletteIndex = (red * I8_GREEN_LEVELS + green) * I8_BLUE_LEVELS + blue;
|
|
192
|
-
const paletteOffset = paletteIndex * 4;
|
|
193
|
-
// LVGL stores its ARGB8888 palette as B, G, R, A bytes on little-endian devices.
|
|
194
|
-
rawData[paletteOffset] = expandChannel(blue, I8_BLUE_LEVELS);
|
|
195
|
-
rawData[paletteOffset + 1] = expandChannel(green, I8_GREEN_LEVELS);
|
|
196
|
-
rawData[paletteOffset + 2] = expandChannel(red, I8_RED_LEVELS);
|
|
197
|
-
rawData[paletteOffset + 3] = 0xff;
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
for (let pixel = 0; pixel < width * height; pixel += 1) {
|
|
203
|
-
const sourceOffset = pixel * 4;
|
|
204
|
-
const alpha = rgba[sourceOffset + 3];
|
|
205
|
-
const red = Math.round((rgba[sourceOffset] * alpha) / 0xff);
|
|
206
|
-
const green = Math.round((rgba[sourceOffset + 1] * alpha) / 0xff);
|
|
207
|
-
const blue = Math.round((rgba[sourceOffset + 2] * alpha) / 0xff);
|
|
208
|
-
const paletteIndex =
|
|
209
|
-
(quantizeChannel(red, I8_RED_LEVELS) * I8_GREEN_LEVELS +
|
|
210
|
-
quantizeChannel(green, I8_GREEN_LEVELS)) *
|
|
211
|
-
I8_BLUE_LEVELS +
|
|
212
|
-
quantizeChannel(blue, I8_BLUE_LEVELS);
|
|
213
|
-
rawData[I8_PALETTE_SIZE + pixel] = paletteIndex;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
const compressed = compressLz4Block(rawData);
|
|
217
|
-
const data = new Uint8Array(24 + compressed.byteLength);
|
|
218
|
-
const view = new DataView(data.buffer);
|
|
219
|
-
data[0] = 0x19;
|
|
220
|
-
data[1] = COLOR_FORMAT_I8;
|
|
221
|
-
view.setUint16(2, IMAGE_FLAG_COMPRESSED, true);
|
|
222
|
-
view.setUint16(4, width, true);
|
|
223
|
-
view.setUint16(6, height, true);
|
|
224
|
-
view.setUint16(8, stride, true);
|
|
225
|
-
view.setUint16(10, 0, true);
|
|
226
|
-
view.setUint32(12, IMAGE_COMPRESSION_LZ4, true);
|
|
227
|
-
view.setUint32(16, compressed.byteLength, true);
|
|
228
|
-
view.setUint32(20, rawData.byteLength, true);
|
|
229
|
-
data.set(compressed, 24);
|
|
230
|
-
return { data, colorFormat: 'I8' };
|
|
231
|
-
}
|
|
232
|
-
|
|
233
41
|
export function encodePro2Image(options: {
|
|
234
42
|
width: number;
|
|
235
43
|
height: number;
|
|
@@ -317,10 +125,6 @@ export function encodePro2Wallpaper(options: {
|
|
|
317
125
|
width: number;
|
|
318
126
|
height: number;
|
|
319
127
|
rgba: Uint8Array | ArrayBuffer;
|
|
320
|
-
encoding?: Pro2WallpaperEncoding;
|
|
321
128
|
}): { data: Uint8Array; colorFormat: Pro2WallpaperColorFormat } {
|
|
322
|
-
if (options.encoding === 'i8-lz4') {
|
|
323
|
-
return encodePro2I8Lz4(options);
|
|
324
|
-
}
|
|
325
129
|
return encodePro2Image(options);
|
|
326
130
|
}
|