@microbit/microbit-connection 0.0.0-tab.change.177 → 0.9.0-apps.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/LICENSE.md +21 -0
- package/README.md +94 -5
- package/build/cjs/accelerometer-service.d.ts +18 -0
- package/build/cjs/accelerometer-service.js +105 -0
- package/build/cjs/accelerometer-service.js.map +1 -0
- package/build/cjs/accelerometer.js +16 -0
- package/build/cjs/accelerometer.js.map +1 -0
- package/build/{async-util.d.ts → cjs/async-util.d.ts} +9 -0
- package/build/cjs/async-util.js +47 -0
- package/build/cjs/async-util.js.map +1 -0
- package/build/cjs/bluetooth-device-wrapper.d.ts +97 -0
- package/build/cjs/bluetooth-device-wrapper.js +486 -0
- package/build/cjs/bluetooth-device-wrapper.js.map +1 -0
- package/build/{bluetooth-profile.d.ts → cjs/bluetooth-profile.d.ts} +43 -35
- package/build/cjs/bluetooth-profile.js +92 -0
- package/build/cjs/bluetooth-profile.js.map +1 -0
- package/build/cjs/bluetooth.d.ts +112 -0
- package/build/cjs/bluetooth.js +458 -0
- package/build/cjs/bluetooth.js.map +1 -0
- package/build/cjs/board-id.js +81 -0
- package/build/cjs/board-id.js.map +1 -0
- package/build/cjs/board-serial-info.js +51 -0
- package/build/cjs/board-serial-info.js.map +1 -0
- package/build/cjs/button-service.d.ts +13 -0
- package/build/cjs/button-service.js +66 -0
- package/build/cjs/button-service.js.map +1 -0
- package/build/cjs/buttons.js +22 -0
- package/build/cjs/buttons.js.map +1 -0
- package/build/cjs/constants.js +73 -0
- package/build/cjs/constants.js.map +1 -0
- package/build/cjs/device-information-service.d.ts +6 -0
- package/build/cjs/device-information-service.js +34 -0
- package/build/cjs/device-information-service.js.map +1 -0
- package/build/{device.d.ts → cjs/device.d.ts} +71 -39
- package/build/cjs/device.js +147 -0
- package/build/cjs/device.js.map +1 -0
- package/build/cjs/dfu-service.d.ts +9 -0
- package/build/cjs/dfu-service.js +26 -0
- package/build/cjs/dfu-service.js.map +1 -0
- package/build/{events.d.ts → cjs/events.d.ts} +1 -2
- package/build/cjs/events.js +109 -0
- package/build/cjs/events.js.map +1 -0
- package/build/cjs/flashing/flashing-full.d.ts +14 -0
- package/build/cjs/flashing/flashing-full.js +87 -0
- package/build/cjs/flashing/flashing-full.js.map +1 -0
- package/build/cjs/flashing/flashing-makecode.d.ts +6 -0
- package/build/cjs/flashing/flashing-makecode.js +48 -0
- package/build/cjs/flashing/flashing-makecode.js.map +1 -0
- package/build/cjs/flashing/flashing-partial.d.ts +9 -0
- package/build/cjs/flashing/flashing-partial.js +98 -0
- package/build/cjs/flashing/flashing-partial.js.map +1 -0
- package/build/cjs/flashing/flashing-v1.d.ts +11 -0
- package/build/cjs/flashing/flashing-v1.js +24 -0
- package/build/cjs/flashing/flashing-v1.js.map +1 -0
- package/build/cjs/flashing/nordic-dfu.d.ts +3 -0
- package/build/cjs/flashing/nordic-dfu.js +214 -0
- package/build/cjs/flashing/nordic-dfu.js.map +1 -0
- package/build/cjs/flashing/zip.d.ts +12 -0
- package/build/cjs/flashing/zip.js +177 -0
- package/build/cjs/flashing/zip.js.map +1 -0
- package/build/cjs/hex-flash-data-source.js +26 -0
- package/build/cjs/hex-flash-data-source.js.map +1 -0
- package/build/cjs/index.d.ts +17 -0
- package/build/cjs/index.js +37 -0
- package/build/cjs/index.js.map +1 -0
- package/build/cjs/led-service.d.ts +18 -0
- package/build/cjs/led-service.js +89 -0
- package/build/cjs/led-service.js.map +1 -0
- package/build/cjs/led.js +3 -0
- package/build/cjs/led.js.map +1 -0
- package/build/{logging.d.ts → cjs/logging.d.ts} +4 -4
- package/build/cjs/logging.js +16 -0
- package/build/cjs/logging.js.map +1 -0
- package/build/cjs/magnetometer-service.d.ts +18 -0
- package/build/cjs/magnetometer-service.js +94 -0
- package/build/cjs/magnetometer-service.js.map +1 -0
- package/build/cjs/magnetometer.d.ts +9 -0
- package/build/cjs/magnetometer.js +16 -0
- package/build/cjs/magnetometer.js.map +1 -0
- package/build/cjs/package.json +1 -0
- package/build/cjs/partial-flashing-service.d.ts +45 -0
- package/build/cjs/partial-flashing-service.js +110 -0
- package/build/cjs/partial-flashing-service.js.map +1 -0
- package/build/cjs/promise-queue.js +78 -0
- package/build/cjs/promise-queue.js.map +1 -0
- package/build/cjs/serial-events.d.ts +20 -0
- package/build/cjs/serial-events.js +69 -0
- package/build/cjs/serial-events.js.map +1 -0
- package/build/{service-events.d.ts → cjs/service-events.d.ts} +4 -0
- package/build/cjs/service-events.js +39 -0
- package/build/cjs/service-events.js.map +1 -0
- package/build/cjs/setupTests.js.map +1 -0
- package/build/cjs/uart-service.d.ts +12 -0
- package/build/cjs/uart-service.js +55 -0
- package/build/cjs/uart-service.js.map +1 -0
- package/build/cjs/uart.d.ts +4 -0
- package/build/cjs/uart.js +16 -0
- package/build/cjs/uart.js.map +1 -0
- package/build/{usb-device-wrapper.d.ts → cjs/usb-device-wrapper.d.ts} +1 -6
- package/build/cjs/usb-device-wrapper.js +437 -0
- package/build/cjs/usb-device-wrapper.js.map +1 -0
- package/build/cjs/usb-partial-flashing-utils.js +133 -0
- package/build/cjs/usb-partial-flashing-utils.js.map +1 -0
- package/build/{usb-partial-flashing.d.ts → cjs/usb-partial-flashing.d.ts} +3 -5
- package/build/cjs/usb-partial-flashing.js +342 -0
- package/build/cjs/usb-partial-flashing.js.map +1 -0
- package/build/cjs/usb-radio-bridge.d.ts +24 -0
- package/build/cjs/usb-radio-bridge.js +515 -0
- package/build/cjs/usb-radio-bridge.js.map +1 -0
- package/build/cjs/usb-serial-protocol.js +183 -0
- package/build/cjs/usb-serial-protocol.js.map +1 -0
- package/build/cjs/usb.d.ts +66 -0
- package/build/cjs/usb.js +662 -0
- package/build/cjs/usb.js.map +1 -0
- package/build/esm/accelerometer-service.d.ts +18 -0
- package/build/esm/accelerometer-service.js +101 -0
- package/build/esm/accelerometer-service.js.map +1 -0
- package/build/esm/accelerometer.d.ts +9 -0
- package/build/esm/accelerometer.js.map +1 -0
- package/build/esm/async-util.d.ts +22 -0
- package/build/esm/async-util.js +38 -0
- package/build/esm/async-util.js.map +1 -0
- package/build/esm/bluetooth-device-wrapper.d.ts +97 -0
- package/build/esm/bluetooth-device-wrapper.js +481 -0
- package/build/esm/bluetooth-device-wrapper.js.map +1 -0
- package/build/esm/bluetooth-profile.d.ts +147 -0
- package/build/{bluetooth-profile.js → esm/bluetooth-profile.js} +35 -29
- package/build/esm/bluetooth-profile.js.map +1 -0
- package/build/esm/bluetooth.d.ts +112 -0
- package/build/esm/bluetooth.js +428 -0
- package/build/esm/bluetooth.js.map +1 -0
- package/build/esm/board-id.d.ts +36 -0
- package/build/esm/board-id.js.map +1 -0
- package/build/esm/board-serial-info.d.ts +14 -0
- package/build/esm/board-serial-info.js.map +1 -0
- package/build/esm/button-service.d.ts +13 -0
- package/build/esm/button-service.js +62 -0
- package/build/esm/button-service.js.map +1 -0
- package/build/esm/buttons.d.ts +10 -0
- package/build/esm/buttons.js.map +1 -0
- package/build/esm/constants.d.ts +48 -0
- package/build/esm/constants.js.map +1 -0
- package/build/esm/device-information-service.d.ts +6 -0
- package/build/esm/device-information-service.js +30 -0
- package/build/esm/device-information-service.js.map +1 -0
- package/build/esm/device.d.ts +238 -0
- package/build/{device.js → esm/device.js} +16 -58
- package/build/esm/device.js.map +1 -0
- package/build/esm/dfu-service.d.ts +9 -0
- package/build/esm/dfu-service.js +22 -0
- package/build/esm/dfu-service.js.map +1 -0
- package/build/esm/events.d.ts +110 -0
- package/build/esm/events.js.map +1 -0
- package/build/esm/flashing/flashing-full.d.ts +14 -0
- package/build/esm/flashing/flashing-full.js +84 -0
- package/build/esm/flashing/flashing-full.js.map +1 -0
- package/build/esm/flashing/flashing-makecode.d.ts +6 -0
- package/build/esm/flashing/flashing-makecode.js +44 -0
- package/build/esm/flashing/flashing-makecode.js.map +1 -0
- package/build/esm/flashing/flashing-partial.d.ts +9 -0
- package/build/esm/flashing/flashing-partial.js +95 -0
- package/build/esm/flashing/flashing-partial.js.map +1 -0
- package/build/esm/flashing/flashing-v1.d.ts +11 -0
- package/build/esm/flashing/flashing-v1.js +20 -0
- package/build/esm/flashing/flashing-v1.js.map +1 -0
- package/build/esm/flashing/nordic-dfu.d.ts +3 -0
- package/build/esm/flashing/nordic-dfu.js +211 -0
- package/build/esm/flashing/nordic-dfu.js.map +1 -0
- package/build/esm/flashing/zip.d.ts +12 -0
- package/build/esm/flashing/zip.js +174 -0
- package/build/esm/flashing/zip.js.map +1 -0
- package/build/esm/hex-flash-data-source.d.ts +7 -0
- package/build/esm/hex-flash-data-source.js.map +1 -0
- package/build/esm/index.d.ts +17 -0
- package/build/esm/index.js +12 -0
- package/build/esm/index.js.map +1 -0
- package/build/esm/led-service.d.ts +18 -0
- package/build/esm/led-service.js +85 -0
- package/build/esm/led-service.js.map +1 -0
- package/build/esm/led.d.ts +6 -0
- package/build/esm/led.js.map +1 -0
- package/build/esm/logging.d.ts +21 -0
- package/build/{logging.js → esm/logging.js} +1 -1
- package/build/esm/logging.js.map +1 -0
- package/build/esm/magnetometer-service.d.ts +18 -0
- package/build/esm/magnetometer-service.js +90 -0
- package/build/esm/magnetometer-service.js.map +1 -0
- package/build/esm/magnetometer.d.ts +9 -0
- package/build/esm/magnetometer.js +12 -0
- package/build/esm/magnetometer.js.map +1 -0
- package/build/esm/package.json +1 -0
- package/build/esm/partial-flashing-service.d.ts +45 -0
- package/build/esm/partial-flashing-service.js +106 -0
- package/build/esm/partial-flashing-service.js.map +1 -0
- package/build/esm/promise-queue.d.ts +27 -0
- package/build/esm/promise-queue.js.map +1 -0
- package/build/esm/serial-events.d.ts +20 -0
- package/build/esm/serial-events.js +61 -0
- package/build/esm/serial-events.js.map +1 -0
- package/build/esm/service-events.d.ts +17 -0
- package/build/{service-events.js → esm/service-events.js} +12 -0
- package/build/esm/service-events.js.map +1 -0
- package/build/esm/setupTests.d.ts +6 -0
- package/build/{setupTests.js.map → esm/setupTests.js.map} +1 -1
- package/build/esm/uart-service.d.ts +12 -0
- package/build/esm/uart-service.js +51 -0
- package/build/esm/uart-service.js.map +1 -0
- package/build/esm/uart.d.ts +4 -0
- package/build/esm/uart.js +12 -0
- package/build/esm/uart.js.map +1 -0
- package/build/esm/usb-device-wrapper.d.ts +47 -0
- package/build/{usb-device-wrapper.js → esm/usb-device-wrapper.js} +43 -17
- package/build/esm/usb-device-wrapper.js.map +1 -0
- package/build/esm/usb-partial-flashing-utils.d.ts +17 -0
- package/build/esm/usb-partial-flashing-utils.js.map +1 -0
- package/build/esm/usb-partial-flashing.d.ts +67 -0
- package/build/{usb-partial-flashing.js → esm/usb-partial-flashing.js} +12 -13
- package/build/esm/usb-partial-flashing.js.map +1 -0
- package/build/esm/usb-radio-bridge.d.ts +24 -0
- package/build/{usb-radio-bridge.js → esm/usb-radio-bridge.js} +13 -7
- package/build/esm/usb-radio-bridge.js.map +1 -0
- package/build/esm/usb-serial-protocol.d.ts +66 -0
- package/build/esm/usb-serial-protocol.js.map +1 -0
- package/build/esm/usb.d.ts +66 -0
- package/build/{usb.js → esm/usb.js} +257 -49
- package/build/esm/usb.js.map +1 -0
- package/package.json +25 -8
- package/typedoc.json +14 -0
- package/build/accelerometer-service.d.ts +0 -18
- package/build/accelerometer-service.js +0 -102
- package/build/accelerometer-service.js.map +0 -1
- package/build/accelerometer.js.map +0 -1
- package/build/async-util.js +0 -22
- package/build/async-util.js.map +0 -1
- package/build/bluetooth-device-wrapper.d.ts +0 -57
- package/build/bluetooth-device-wrapper.js +0 -433
- package/build/bluetooth-device-wrapper.js.map +0 -1
- package/build/bluetooth-profile.js.map +0 -1
- package/build/bluetooth.d.ts +0 -54
- package/build/bluetooth.js +0 -243
- package/build/bluetooth.js.map +0 -1
- package/build/board-id.js.map +0 -1
- package/build/board-serial-info.js.map +0 -1
- package/build/button-service.d.ts +0 -13
- package/build/button-service.js +0 -76
- package/build/button-service.js.map +0 -1
- package/build/buttons.js.map +0 -1
- package/build/constants.js.map +0 -1
- package/build/device.js.map +0 -1
- package/build/events.js.map +0 -1
- package/build/hex-flash-data-source.js.map +0 -1
- package/build/index.d.ts +0 -10
- package/build/index.js +0 -8
- package/build/index.js.map +0 -1
- package/build/led-service.d.ts +0 -20
- package/build/led-service.js +0 -116
- package/build/led-service.js.map +0 -1
- package/build/led.js.map +0 -1
- package/build/logging.js.map +0 -1
- package/build/promise-queue.js.map +0 -1
- package/build/service-events.js.map +0 -1
- package/build/usb-device-wrapper.js.map +0 -1
- package/build/usb-partial-flashing-utils.js.map +0 -1
- package/build/usb-partial-flashing.js.map +0 -1
- package/build/usb-radio-bridge.d.ts +0 -41
- package/build/usb-radio-bridge.js.map +0 -1
- package/build/usb-serial-protocol.js.map +0 -1
- package/build/usb.d.ts +0 -54
- package/build/usb.js.map +0 -1
- package/vite.config.ts +0 -34
- /package/build/{accelerometer.d.ts → cjs/accelerometer.d.ts} +0 -0
- /package/build/{board-id.d.ts → cjs/board-id.d.ts} +0 -0
- /package/build/{board-serial-info.d.ts → cjs/board-serial-info.d.ts} +0 -0
- /package/build/{buttons.d.ts → cjs/buttons.d.ts} +0 -0
- /package/build/{constants.d.ts → cjs/constants.d.ts} +0 -0
- /package/build/{hex-flash-data-source.d.ts → cjs/hex-flash-data-source.d.ts} +0 -0
- /package/build/{led.d.ts → cjs/led.d.ts} +0 -0
- /package/build/{promise-queue.d.ts → cjs/promise-queue.d.ts} +0 -0
- /package/build/{setupTests.d.ts → cjs/setupTests.d.ts} +0 -0
- /package/build/{usb-partial-flashing-utils.d.ts → cjs/usb-partial-flashing-utils.d.ts} +0 -0
- /package/build/{usb-serial-protocol.d.ts → cjs/usb-serial-protocol.d.ts} +0 -0
- /package/build/{accelerometer.js → esm/accelerometer.js} +0 -0
- /package/build/{board-id.js → esm/board-id.js} +0 -0
- /package/build/{board-serial-info.js → esm/board-serial-info.js} +0 -0
- /package/build/{buttons.js → esm/buttons.js} +0 -0
- /package/build/{constants.js → esm/constants.js} +0 -0
- /package/build/{events.js → esm/events.js} +0 -0
- /package/build/{hex-flash-data-source.js → esm/hex-flash-data-source.js} +0 -0
- /package/build/{led.js → esm/led.js} +0 -0
- /package/build/{promise-queue.js → esm/promise-queue.js} +0 -0
- /package/build/{usb-partial-flashing-utils.js → esm/usb-partial-flashing-utils.js} +0 -0
- /package/build/{usb-serial-protocol.js → esm/usb-serial-protocol.js} +0 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2022 Jonas "DerZade" Schade
|
|
3
|
+
*
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*
|
|
6
|
+
* https://github.com/DerZade/typescript-event-target/blob/master/src/TypedEventTarget.ts
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* A function that can be passed to the `listener` parameter of {@link TypedEventTarget.addEventListener} and {@link TypedEventTarget.removeEventListener}.
|
|
10
|
+
*
|
|
11
|
+
* @template M A map of event types to their respective event classes.
|
|
12
|
+
* @template T The type of event to listen for (has to be keyof `M`).
|
|
13
|
+
*/
|
|
14
|
+
export type TypedEventListener<M, T extends keyof M> = (evt: M[T]) => void | Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* An object that can be passed to the `listener` parameter of {@link TypedEventTarget.addEventListener} and {@link TypedEventTarget.removeEventListener}.
|
|
17
|
+
*
|
|
18
|
+
* @template M A map of event types to their respective event classes.
|
|
19
|
+
* @template T The type of event to listen for (has to be keyof `M`).
|
|
20
|
+
*/
|
|
21
|
+
export interface TypedEventListenerObject<M, T extends keyof M> {
|
|
22
|
+
handleEvent: (evt: M[T]) => void | Promise<void>;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Type of parameter `listener` in {@link TypedEventTarget.addEventListener} and {@link TypedEventTarget.removeEventListener}.
|
|
26
|
+
*
|
|
27
|
+
* The object that receives a notification (an object that implements the Event interface) when an event of the specified type occurs.
|
|
28
|
+
*
|
|
29
|
+
* Can be either an object with a handleEvent() method, or a JavaScript function.
|
|
30
|
+
*
|
|
31
|
+
* @template M A map of event types to their respective event classes.
|
|
32
|
+
* @template T The type of event to listen for (has to be keyof `M`).
|
|
33
|
+
*/
|
|
34
|
+
export type TypedEventListenerOrEventListenerObject<M, T extends keyof M> = TypedEventListener<M, T> | TypedEventListenerObject<M, T>;
|
|
35
|
+
export type ValueIsEvent<T> = {
|
|
36
|
+
[key in keyof T]: Event;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Typescript friendly version of {@link EventTarget}
|
|
40
|
+
*
|
|
41
|
+
* @template M A map of event types to their respective event classes.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```typescript
|
|
45
|
+
* interface MyEventMap {
|
|
46
|
+
* hello: Event;
|
|
47
|
+
* time: CustomEvent<number>;
|
|
48
|
+
* }
|
|
49
|
+
*
|
|
50
|
+
* const eventTarget = new TypedEventTarget<MyEventMap>();
|
|
51
|
+
*
|
|
52
|
+
* eventTarget.addEventListener('time', (event) => {
|
|
53
|
+
* // event is of type CustomEvent<number>
|
|
54
|
+
* });
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export interface TypedEventTarget<M extends ValueIsEvent<M>> {
|
|
58
|
+
/** Appends an event listener for events whose type attribute value is type.
|
|
59
|
+
* The callback argument sets the callback that will be invoked when the event
|
|
60
|
+
* is dispatched.
|
|
61
|
+
*
|
|
62
|
+
* The options argument sets listener-specific options. For compatibility this
|
|
63
|
+
* can be a boolean, in which case the method behaves exactly as if the value
|
|
64
|
+
* was specified as options's capture.
|
|
65
|
+
*
|
|
66
|
+
* When set to true, options's capture prevents callback from being invoked
|
|
67
|
+
* when the event's eventPhase attribute value is BUBBLING_PHASE. When false
|
|
68
|
+
* (or not present), callback will not be invoked when event's eventPhase
|
|
69
|
+
* attribute value is CAPTURING_PHASE. Either way, callback will be invoked if
|
|
70
|
+
* event's eventPhase attribute value is AT_TARGET.
|
|
71
|
+
*
|
|
72
|
+
* When set to true, options's passive indicates that the callback will not
|
|
73
|
+
* cancel the event by invoking preventDefault(). This is used to enable
|
|
74
|
+
* performance optimizations described in § 2.8 Observing event listeners.
|
|
75
|
+
*
|
|
76
|
+
* When set to true, options's once indicates that the callback will only be
|
|
77
|
+
* invoked once after which the event listener will be removed.
|
|
78
|
+
*
|
|
79
|
+
* The event listener is appended to target's event listener list and is not
|
|
80
|
+
* appended if it has the same type, callback, and capture. */
|
|
81
|
+
addEventListener: <T extends keyof M & string>(type: T, listener: TypedEventListenerOrEventListenerObject<M, T> | null, options?: boolean | AddEventListenerOptions) => void;
|
|
82
|
+
/** Removes the event listener in target's event listener list with the same
|
|
83
|
+
* type, callback, and options. */
|
|
84
|
+
removeEventListener: <T extends keyof M & string>(type: T, callback: TypedEventListenerOrEventListenerObject<M, T> | null, options?: EventListenerOptions | boolean) => void;
|
|
85
|
+
/**
|
|
86
|
+
* Dispatches a synthetic event event to target and returns true if either
|
|
87
|
+
* event's cancelable attribute value is false or its preventDefault() method
|
|
88
|
+
* was not invoked, and false otherwise.
|
|
89
|
+
* @deprecated To ensure type safety use `dispatchTypedEvent` instead.
|
|
90
|
+
*/
|
|
91
|
+
dispatchEvent: (event: Event) => boolean;
|
|
92
|
+
}
|
|
93
|
+
export declare class TrackingEventTarget extends EventTarget {
|
|
94
|
+
private activeEventTracking;
|
|
95
|
+
addEventListener(type: string, callback: EventListenerOrEventListenerObject | null, options?: AddEventListenerOptions | boolean): void;
|
|
96
|
+
removeEventListener(type: string, callback: EventListenerOrEventListenerObject | null, options?: EventListenerOptions | boolean): void;
|
|
97
|
+
dispatchEvent(event: Event): boolean;
|
|
98
|
+
private filterRegistrations;
|
|
99
|
+
protected eventActivated(type: string): void;
|
|
100
|
+
protected eventDeactivated(type: string): void;
|
|
101
|
+
protected getActiveEvents(): string[];
|
|
102
|
+
}
|
|
103
|
+
export declare class TypedEventTarget<M extends ValueIsEvent<M>> extends TrackingEventTarget {
|
|
104
|
+
/**
|
|
105
|
+
* Dispatches a synthetic event event to target and returns true if either
|
|
106
|
+
* event's cancelable attribute value is false or its preventDefault() method
|
|
107
|
+
* was not invoked, and false otherwise.
|
|
108
|
+
*/
|
|
109
|
+
dispatchTypedEvent<T extends keyof M>(_type: T, event: M[T]): boolean;
|
|
110
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../lib/events.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import MemoryMap from "nrf-intel-hex";
|
|
2
|
+
import { BoardVersion, ProgressCallback } from "../device";
|
|
3
|
+
import { BluetoothDeviceWrapper } from "../bluetooth-device-wrapper";
|
|
4
|
+
/**
|
|
5
|
+
* Perform a full flash via Nordic's DFU service.
|
|
6
|
+
*
|
|
7
|
+
* The connection is closed before handing off to Nordic's service which will
|
|
8
|
+
* connect again.
|
|
9
|
+
*
|
|
10
|
+
* The device is assumed to be bonded.
|
|
11
|
+
*
|
|
12
|
+
* @throws {DeviceError} On flash failure.
|
|
13
|
+
*/
|
|
14
|
+
export declare function fullFlash(connection: BluetoothDeviceWrapper, boardVersion: BoardVersion, memoryMap: MemoryMap, progress: ProgressCallback): Promise<void>;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { DeviceError, FlashDataError, ProgressStage, } from "../device";
|
|
2
|
+
import { DfuService, NORDIC_DFU_SERVICE } from "../dfu-service";
|
|
3
|
+
import { refreshServicesForV1IfDesiredServiceMissing } from "./flashing-v1";
|
|
4
|
+
import { flashDfu } from "./nordic-dfu";
|
|
5
|
+
import { delay } from "../async-util";
|
|
6
|
+
/**
|
|
7
|
+
* Perform a full flash via Nordic's DFU service.
|
|
8
|
+
*
|
|
9
|
+
* The connection is closed before handing off to Nordic's service which will
|
|
10
|
+
* connect again.
|
|
11
|
+
*
|
|
12
|
+
* The device is assumed to be bonded.
|
|
13
|
+
*
|
|
14
|
+
* @throws {DeviceError} On flash failure.
|
|
15
|
+
*/
|
|
16
|
+
export async function fullFlash(connection, boardVersion, memoryMap, progress) {
|
|
17
|
+
connection.log("Full flash");
|
|
18
|
+
progress(ProgressStage.FullFlashing);
|
|
19
|
+
const { deviceId } = connection.device;
|
|
20
|
+
try {
|
|
21
|
+
if (boardVersion === "V1") {
|
|
22
|
+
connection.log("Rebooting V1 to bootloader");
|
|
23
|
+
const dfuService = new DfuService(deviceId);
|
|
24
|
+
try {
|
|
25
|
+
await dfuService.requestRebootToBootloader();
|
|
26
|
+
}
|
|
27
|
+
catch (e) {
|
|
28
|
+
connection.error("Failed to request reboot to bootloader", e);
|
|
29
|
+
throw new DeviceError({
|
|
30
|
+
code: "flash-full-failed",
|
|
31
|
+
message: e instanceof Error ? e.message : "Failed to reboot to bootloader",
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
// Wait for device to automatically disconnect as it reboots into bootloader
|
|
35
|
+
connection.log("Waiting for device to reboot and disconnect");
|
|
36
|
+
try {
|
|
37
|
+
await connection.waitForDisconnect(3000);
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
connection.log("Device did not disconnect automatically, disconnecting manually");
|
|
41
|
+
await connection.disconnect();
|
|
42
|
+
}
|
|
43
|
+
// Give device time to disconnect and reboot into bootloader mode
|
|
44
|
+
await delay(2500);
|
|
45
|
+
// Reconnect to device now in bootloader mode
|
|
46
|
+
progress(ProgressStage.Connecting);
|
|
47
|
+
await connection.connect();
|
|
48
|
+
await refreshServicesForV1IfDesiredServiceMissing(deviceId, NORDIC_DFU_SERVICE);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
// The Nordic code opens its own connection.
|
|
53
|
+
await connection.disconnect();
|
|
54
|
+
// If we've previously been connected, maybe this helps???
|
|
55
|
+
await delay(3000);
|
|
56
|
+
}
|
|
57
|
+
const appBin = createAppBin(memoryMap, boardVersion);
|
|
58
|
+
if (appBin === null) {
|
|
59
|
+
connection.log("Invalid hex (app bin case)");
|
|
60
|
+
throw new FlashDataError("Invalid hex data: could not extract app binary");
|
|
61
|
+
}
|
|
62
|
+
connection.log(`Extracted app bin: ${appBin.length} bytes`);
|
|
63
|
+
await flashDfu(connection, boardVersion, appBin, progress);
|
|
64
|
+
}
|
|
65
|
+
const createAppBin = (memoryMap, boardVersion) => {
|
|
66
|
+
const appRegionBoundaries = {
|
|
67
|
+
V1: { start: 0x18000, end: 0x3c000 },
|
|
68
|
+
V2: { start: 0x1c000, end: 0x77000 },
|
|
69
|
+
}[boardVersion];
|
|
70
|
+
// Calculate data size within the app region
|
|
71
|
+
let maxAddress = appRegionBoundaries.start;
|
|
72
|
+
for (const [blockAddr, block] of memoryMap) {
|
|
73
|
+
const blockEnd = blockAddr + block.length;
|
|
74
|
+
if (blockEnd > appRegionBoundaries.start &&
|
|
75
|
+
blockAddr < appRegionBoundaries.end) {
|
|
76
|
+
maxAddress = Math.max(maxAddress, Math.min(blockEnd, appRegionBoundaries.end));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
let size = maxAddress - appRegionBoundaries.start;
|
|
80
|
+
// 4-byte alignment required by DFU
|
|
81
|
+
size = Math.ceil(size / 4) * 4;
|
|
82
|
+
return memoryMap.slicePad(appRegionBoundaries.start, size);
|
|
83
|
+
};
|
|
84
|
+
//# sourceMappingURL=flashing-full.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flashing-full.js","sourceRoot":"","sources":["../../../lib/flashing/flashing-full.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,WAAW,EACX,cAAc,EAEd,aAAa,GACd,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,2CAA2C,EAAE,MAAM,eAAe,CAAC;AAC5E,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAEtC;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,UAAkC,EAClC,YAA0B,EAC1B,SAAoB,EACpB,QAA0B;IAE1B,UAAU,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAC7B,QAAQ,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;IACrC,MAAM,EAAE,QAAQ,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC;IAEvC,IAAI,CAAC;QACH,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;YAC1B,UAAU,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;YAE7C,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC;YAC5C,IAAI,CAAC;gBACH,MAAM,UAAU,CAAC,yBAAyB,EAAE,CAAC;YAC/C,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,UAAU,CAAC,KAAK,CAAC,wCAAwC,EAAE,CAAC,CAAC,CAAC;gBAC9D,MAAM,IAAI,WAAW,CAAC;oBACpB,IAAI,EAAE,mBAAmB;oBACzB,OAAO,EACL,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,gCAAgC;iBACpE,CAAC,CAAC;YACL,CAAC;YAED,4EAA4E;YAC5E,UAAU,CAAC,GAAG,CAAC,6CAA6C,CAAC,CAAC;YAC9D,IAAI,CAAC;gBACH,MAAM,UAAU,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAC3C,CAAC;YAAC,MAAM,CAAC;gBACP,UAAU,CAAC,GAAG,CACZ,iEAAiE,CAClE,CAAC;gBACF,MAAM,UAAU,CAAC,UAAU,EAAE,CAAC;YAChC,CAAC;YAED,iEAAiE;YACjE,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;YAElB,6CAA6C;YAC7C,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;YACnC,MAAM,UAAU,CAAC,OAAO,EAAE,CAAC;YAC3B,MAAM,2CAA2C,CAC/C,QAAQ,EACR,kBAAkB,CACnB,CAAC;QACJ,CAAC;IACH,CAAC;YAAS,CAAC;QACT,4CAA4C;QAC5C,MAAM,UAAU,CAAC,UAAU,EAAE,CAAC;QAE9B,0DAA0D;QAC1D,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC;IAED,MAAM,MAAM,GAAG,YAAY,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IACrD,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACpB,UAAU,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;QAC7C,MAAM,IAAI,cAAc,CAAC,gDAAgD,CAAC,CAAC;IAC7E,CAAC;IACD,UAAU,CAAC,GAAG,CAAC,sBAAsB,MAAM,CAAC,MAAM,QAAQ,CAAC,CAAC;IAC5D,MAAM,QAAQ,CAAC,UAAU,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,YAAY,GAAG,CACnB,SAAoB,EACpB,YAA0B,EACP,EAAE;IACrB,MAAM,mBAAmB,GAAG;QAC1B,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE;QACpC,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE;KACrC,CAAC,YAAY,CAAC,CAAC;IAEhB,4CAA4C;IAC5C,IAAI,UAAU,GAAG,mBAAmB,CAAC,KAAK,CAAC;IAC3C,KAAK,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,SAAS,EAAE,CAAC;QAC3C,MAAM,QAAQ,GAAG,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC;QAC1C,IACE,QAAQ,GAAG,mBAAmB,CAAC,KAAK;YACpC,SAAS,GAAG,mBAAmB,CAAC,GAAG,EACnC,CAAC;YACD,UAAU,GAAG,IAAI,CAAC,GAAG,CACnB,UAAU,EACV,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,mBAAmB,CAAC,GAAG,CAAC,CAC5C,CAAC;QACJ,CAAC;IACH,CAAC;IAED,IAAI,IAAI,GAAG,UAAU,GAAG,mBAAmB,CAAC,KAAK,CAAC;IAClD,mCAAmC;IACnC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IAE/B,OAAO,SAAS,CAAC,QAAQ,CAAC,mBAAmB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AAC7D,CAAC,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import MemoryMap from "nrf-intel-hex";
|
|
2
|
+
import { RegionInfo } from "../partial-flashing-service";
|
|
3
|
+
/**
|
|
4
|
+
* Find the MakeCode code region in a MemoryMap (typically from a hex file).
|
|
5
|
+
*/
|
|
6
|
+
export declare const findMakeCodeRegionInMemoryMap: (memoryMap: MemoryMap, deviceCodeRegion: RegionInfo) => RegionInfo | null;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const PXT_MAGIC_HEX = "708E3B92C615A841C49866C975EE5197";
|
|
2
|
+
/**
|
|
3
|
+
* Find the MakeCode code region in a MemoryMap (typically from a hex file).
|
|
4
|
+
*/
|
|
5
|
+
export const findMakeCodeRegionInMemoryMap = (memoryMap, deviceCodeRegion) => {
|
|
6
|
+
for (const [blockAddr, block] of memoryMap) {
|
|
7
|
+
const offset = findByteSequence(block, PXT_MAGIC_HEX);
|
|
8
|
+
if (offset >= 0) {
|
|
9
|
+
const start = blockAddr + offset;
|
|
10
|
+
const hashOffset = start + PXT_MAGIC_HEX.length / 2;
|
|
11
|
+
const hashBytes = memoryMap.slicePad(hashOffset, 8);
|
|
12
|
+
const hash = bytesToHex(hashBytes);
|
|
13
|
+
// Find the highest address with data in the memory map within the code region
|
|
14
|
+
let end = start;
|
|
15
|
+
for (const [blockAddr, block] of memoryMap) {
|
|
16
|
+
const blockEnd = blockAddr + block.length;
|
|
17
|
+
if (blockEnd > start && blockAddr < deviceCodeRegion.end) {
|
|
18
|
+
end = Math.max(end, Math.min(blockEnd, deviceCodeRegion.end));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
// Round up to next 64-byte boundary
|
|
22
|
+
end = Math.ceil(end / 64) * 64;
|
|
23
|
+
return { start, end, hash };
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
};
|
|
28
|
+
const bytesToHex = (bytes) => {
|
|
29
|
+
return Array.from(bytes)
|
|
30
|
+
.map((byte) => byte.toString(16).padStart(2, "0").toUpperCase())
|
|
31
|
+
.join("");
|
|
32
|
+
};
|
|
33
|
+
function findByteSequence(data, hexTarget) {
|
|
34
|
+
const target = new Uint8Array(hexTarget.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)));
|
|
35
|
+
outer: for (let i = 0; i <= data.length - target.length; i++) {
|
|
36
|
+
for (let j = 0; j < target.length; j++) {
|
|
37
|
+
if (data[i + j] !== target[j])
|
|
38
|
+
continue outer;
|
|
39
|
+
}
|
|
40
|
+
return i;
|
|
41
|
+
}
|
|
42
|
+
return -1;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=flashing-makecode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flashing-makecode.js","sourceRoot":"","sources":["../../../lib/flashing/flashing-makecode.ts"],"names":[],"mappings":"AAGA,MAAM,aAAa,GAAG,kCAAkC,CAAC;AAEzD;;GAEG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAC3C,SAAoB,EACpB,gBAA4B,EACT,EAAE;IACrB,KAAK,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,SAAS,EAAE,CAAC;QAC3C,MAAM,MAAM,GAAG,gBAAgB,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;QACtD,IAAI,MAAM,IAAI,CAAC,EAAE,CAAC;YAChB,MAAM,KAAK,GAAG,SAAS,GAAG,MAAM,CAAC;YACjC,MAAM,UAAU,GAAG,KAAK,GAAG,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC;YACpD,MAAM,SAAS,GAAG,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;YACpD,MAAM,IAAI,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;YAEnC,8EAA8E;YAC9E,IAAI,GAAG,GAAG,KAAK,CAAC;YAChB,KAAK,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,SAAS,EAAE,CAAC;gBAC3C,MAAM,QAAQ,GAAG,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC;gBAC1C,IAAI,QAAQ,GAAG,KAAK,IAAI,SAAS,GAAG,gBAAgB,CAAC,GAAG,EAAE,CAAC;oBACzD,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC;gBAChE,CAAC;YACH,CAAC;YACD,oCAAoC;YACpC,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC;YAE/B,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;QAC9B,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,CAAC,KAAiB,EAAU,EAAE;IAC/C,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;SACrB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;SAC/D,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC,CAAC;AAEF,SAAS,gBAAgB,CAAC,IAAgB,EAAE,SAAiB;IAC3D,MAAM,MAAM,GAAG,IAAI,UAAU,CAC3B,SAAS,CAAC,KAAK,CAAC,SAAS,CAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAC9D,CAAC;IAEF,KAAK,EAAE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACvC,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC;gBAAE,SAAS,KAAK,CAAC;QAChD,CAAC;QACD,OAAO,CAAC,CAAC;IACX,CAAC;IAED,OAAO,CAAC,CAAC,CAAC;AACZ,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import MemoryMap from "nrf-intel-hex";
|
|
2
|
+
import { BluetoothDeviceWrapper } from "../bluetooth-device-wrapper";
|
|
3
|
+
import { ProgressCallback } from "../device";
|
|
4
|
+
export declare enum PartialFlashResult {
|
|
5
|
+
Success = "Success",
|
|
6
|
+
AttemptFullFlash = "AttemptFullFlash"
|
|
7
|
+
}
|
|
8
|
+
declare const partialFlash: (connection: BluetoothDeviceWrapper, memoryMap: MemoryMap, progress: ProgressCallback) => Promise<PartialFlashResult>;
|
|
9
|
+
export default partialFlash;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { PacketState, PartialFlashingService, RegionId, } from "../partial-flashing-service";
|
|
2
|
+
import { findMakeCodeRegionInMemoryMap } from "./flashing-makecode";
|
|
3
|
+
import { delay, DisconnectError } from "../async-util";
|
|
4
|
+
import { DeviceError, ProgressStage } from "../device";
|
|
5
|
+
export var PartialFlashResult;
|
|
6
|
+
(function (PartialFlashResult) {
|
|
7
|
+
PartialFlashResult["Success"] = "Success";
|
|
8
|
+
PartialFlashResult["AttemptFullFlash"] = "AttemptFullFlash";
|
|
9
|
+
})(PartialFlashResult || (PartialFlashResult = {}));
|
|
10
|
+
const partialFlash = async (connection, memoryMap, progress) => {
|
|
11
|
+
const pf = new PartialFlashingService(connection);
|
|
12
|
+
await pf.startNotifications();
|
|
13
|
+
const result = await connection.raceDisconnectAndTimeout(partialFlashInternal(connection, pf, memoryMap, progress), { timeout: 30_000, actionName: "partial flash" });
|
|
14
|
+
try {
|
|
15
|
+
await pf.stopNotifications();
|
|
16
|
+
}
|
|
17
|
+
catch (e) {
|
|
18
|
+
// V1 disconnects quickly after a partial flash.
|
|
19
|
+
if (!(e instanceof DisconnectError)) {
|
|
20
|
+
connection.error("Error stopping notifications", e);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
const partialFlashInternal = async (connection, pf, memoryMap, progress) => {
|
|
26
|
+
connection.log("Partial flash");
|
|
27
|
+
progress(ProgressStage.PartialFlashing);
|
|
28
|
+
try {
|
|
29
|
+
const deviceCodeRegion = await pf.getRegionInfo(RegionId.MakeCode);
|
|
30
|
+
if (deviceCodeRegion === null) {
|
|
31
|
+
connection.log("Could not read code region");
|
|
32
|
+
return PartialFlashResult.AttemptFullFlash;
|
|
33
|
+
}
|
|
34
|
+
const deviceDalRegion = await pf.getRegionInfo(RegionId.Dal);
|
|
35
|
+
if (deviceDalRegion === null) {
|
|
36
|
+
connection.log("Could not read DAL region");
|
|
37
|
+
return PartialFlashResult.AttemptFullFlash;
|
|
38
|
+
}
|
|
39
|
+
progress(ProgressStage.PartialFlashing);
|
|
40
|
+
const fileCodeRegion = findMakeCodeRegionInMemoryMap(memoryMap, deviceCodeRegion);
|
|
41
|
+
if (fileCodeRegion === null) {
|
|
42
|
+
connection.log("No partial flash data");
|
|
43
|
+
return PartialFlashResult.AttemptFullFlash;
|
|
44
|
+
}
|
|
45
|
+
if (fileCodeRegion.hash !== deviceDalRegion.hash) {
|
|
46
|
+
connection.log(`DAL hash comparison failed. Hex: ${fileCodeRegion.hash} vs device: ${deviceDalRegion.hash}`);
|
|
47
|
+
return PartialFlashResult.AttemptFullFlash;
|
|
48
|
+
}
|
|
49
|
+
if (deviceCodeRegion.start !== fileCodeRegion.start) {
|
|
50
|
+
connection.log("Code start address doesn't match");
|
|
51
|
+
return PartialFlashResult.AttemptFullFlash;
|
|
52
|
+
}
|
|
53
|
+
let nextPacketNumber = 0;
|
|
54
|
+
outer: for (let offset = fileCodeRegion.start; offset < fileCodeRegion.end;) {
|
|
55
|
+
const batchStartAddress = offset;
|
|
56
|
+
for (let packetInBatch = 0; packetInBatch < 4; ++packetInBatch) {
|
|
57
|
+
const packetNumber = nextPacketNumber++;
|
|
58
|
+
const packetDataOffset = offset + packetInBatch * 16;
|
|
59
|
+
if (packetInBatch < 3) {
|
|
60
|
+
await pf.writeFlash(memoryMap, batchStartAddress, packetDataOffset, packetNumber, packetInBatch);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
const result = await pf.writeFlashForNotification(memoryMap, batchStartAddress, packetDataOffset, packetNumber, packetInBatch);
|
|
64
|
+
if (result === PacketState.Retransmit) {
|
|
65
|
+
// Retry the whole 64 bytes.
|
|
66
|
+
connection.log(`Retransmit requested at offset ${offset}`);
|
|
67
|
+
continue outer;
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
progress(ProgressStage.PartialFlashing, (offset - fileCodeRegion.start) /
|
|
71
|
+
(fileCodeRegion.end - fileCodeRegion.start));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
offset += 64;
|
|
76
|
+
}
|
|
77
|
+
await delay(100); // allow time for write to complete
|
|
78
|
+
await pf.writeEndOfFlashPacket();
|
|
79
|
+
await delay(100); // allow time for write to complete
|
|
80
|
+
progress(ProgressStage.PartialFlashing, 1);
|
|
81
|
+
return PartialFlashResult.Success;
|
|
82
|
+
}
|
|
83
|
+
catch (e) {
|
|
84
|
+
connection.error("Partial flash failed", e);
|
|
85
|
+
if (e instanceof DeviceError) {
|
|
86
|
+
throw e;
|
|
87
|
+
}
|
|
88
|
+
throw new DeviceError({
|
|
89
|
+
code: "flash-partial-failed",
|
|
90
|
+
message: e instanceof Error ? e.message : String(e),
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
export default partialFlash;
|
|
95
|
+
//# sourceMappingURL=flashing-partial.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flashing-partial.js","sourceRoot":"","sources":["../../../lib/flashing/flashing-partial.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V1 changes the service it offers in application/bootloader mode.
|
|
3
|
+
*
|
|
4
|
+
* We don't trust Android to have an up-to-date copy of services so will fall back
|
|
5
|
+
* to calling internal API via reflection if the desired/expected service is not
|
|
6
|
+
* listed.
|
|
7
|
+
*
|
|
8
|
+
* It might be that this is only needed for older versions of Android where we
|
|
9
|
+
* can't get service changed indications.
|
|
10
|
+
*/
|
|
11
|
+
export declare const refreshServicesForV1IfDesiredServiceMissing: (deviceId: string, desiredServiceUuid: string) => Promise<void>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { BleClient } from "@capacitor-community/bluetooth-le";
|
|
2
|
+
/**
|
|
3
|
+
* V1 changes the service it offers in application/bootloader mode.
|
|
4
|
+
*
|
|
5
|
+
* We don't trust Android to have an up-to-date copy of services so will fall back
|
|
6
|
+
* to calling internal API via reflection if the desired/expected service is not
|
|
7
|
+
* listed.
|
|
8
|
+
*
|
|
9
|
+
* It might be that this is only needed for older versions of Android where we
|
|
10
|
+
* can't get service changed indications.
|
|
11
|
+
*/
|
|
12
|
+
export const refreshServicesForV1IfDesiredServiceMissing = async (deviceId, desiredServiceUuid) => {
|
|
13
|
+
const services = await BleClient.getServices(deviceId);
|
|
14
|
+
const deviceHasService = services.some((s) => s.uuid === desiredServiceUuid);
|
|
15
|
+
if (!deviceHasService) {
|
|
16
|
+
// On Android this does use the refresh reflection hack.
|
|
17
|
+
await BleClient.discoverServices(deviceId);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=flashing-v1.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flashing-v1.js","sourceRoot":"","sources":["../../../lib/flashing/flashing-v1.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AAE9D;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,2CAA2C,GAAG,KAAK,EAC9D,QAAgB,EAChB,kBAA0B,EAC1B,EAAE;IACF,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IACvD,MAAM,gBAAgB,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,kBAAkB,CAAC,CAAC;IAC7E,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,wDAAwD;QACxD,MAAM,SAAS,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { BluetoothDeviceWrapper } from "../bluetooth-device-wrapper";
|
|
2
|
+
import { BoardVersion, ProgressCallback } from "../device";
|
|
3
|
+
export declare function flashDfu(connection: BluetoothDeviceWrapper, boardVersion: BoardVersion, appBin: Uint8Array, progress: ProgressCallback): Promise<void>;
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { Capacitor } from "@capacitor/core";
|
|
2
|
+
import { Directory, Filesystem } from "@capacitor/filesystem";
|
|
3
|
+
import { DfuState, NordicDfu } from "@microbit/capacitor-community-nordic-dfu";
|
|
4
|
+
import { createZip } from "./zip";
|
|
5
|
+
import { DeviceError, ProgressStage, } from "../device";
|
|
6
|
+
const appBinFilename = "application.bin";
|
|
7
|
+
const appDatFilename = "application.dat";
|
|
8
|
+
const manifestData = JSON.stringify({
|
|
9
|
+
manifest: {
|
|
10
|
+
application: {
|
|
11
|
+
bin_file: appBinFilename,
|
|
12
|
+
dat_file: appDatFilename,
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
function uint8ArrayToBase64(uint8Array) {
|
|
17
|
+
let binary = "";
|
|
18
|
+
const len = uint8Array.byteLength;
|
|
19
|
+
for (let i = 0; i < len; i++) {
|
|
20
|
+
binary += String.fromCharCode(uint8Array[i]);
|
|
21
|
+
}
|
|
22
|
+
return btoa(binary);
|
|
23
|
+
}
|
|
24
|
+
async function writeCacheFile(options) {
|
|
25
|
+
const directory = Directory.Cache;
|
|
26
|
+
const { uri } = await Filesystem.writeFile({ directory, ...options });
|
|
27
|
+
return uri;
|
|
28
|
+
}
|
|
29
|
+
async function createDfuZipFile(boardVersion, appBin) {
|
|
30
|
+
const createInitPacket = boardVersion === "V1" ? createLegacyInitPacketV1 : createInitPacketV2;
|
|
31
|
+
const encoder = new TextEncoder();
|
|
32
|
+
const zipData = createZip([
|
|
33
|
+
{ name: appDatFilename, data: createInitPacket(appBin) },
|
|
34
|
+
{ name: appBinFilename, data: appBin },
|
|
35
|
+
{ name: "manifest.json", data: encoder.encode(manifestData) },
|
|
36
|
+
]);
|
|
37
|
+
return await writeCacheFile({
|
|
38
|
+
path: "dfu.zip",
|
|
39
|
+
data: uint8ArrayToBase64(zipData),
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
async function getFilePath(boardVersion, appBin) {
|
|
43
|
+
const uri = await createDfuZipFile(boardVersion, appBin);
|
|
44
|
+
return { uri, filename: "dfu.zip" };
|
|
45
|
+
}
|
|
46
|
+
async function cleanupTemporaryFile(connection, filename) {
|
|
47
|
+
try {
|
|
48
|
+
await Filesystem.deleteFile({
|
|
49
|
+
directory: Directory.Cache,
|
|
50
|
+
path: filename,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
// File might not exist or already deleted, ignore errors
|
|
55
|
+
connection.error(`Could not delete temporary file ${filename}`, error);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export async function flashDfu(connection, boardVersion, appBin, progress) {
|
|
59
|
+
const { device } = connection;
|
|
60
|
+
const { uri: filePath, filename } = await getFilePath(boardVersion, appBin);
|
|
61
|
+
let listener;
|
|
62
|
+
try {
|
|
63
|
+
// eslint-disable-next-line no-async-promise-executor
|
|
64
|
+
await new Promise(async (resolve, reject) => {
|
|
65
|
+
listener = await NordicDfu.addListener("DFUStateChanged", ({ state, data }) => {
|
|
66
|
+
switch (state) {
|
|
67
|
+
case DfuState.DFU_COMPLETED: {
|
|
68
|
+
progress(ProgressStage.FullFlashing, 1);
|
|
69
|
+
resolve();
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
case DfuState.DFU_ABORTED: {
|
|
73
|
+
reject(new DeviceError({
|
|
74
|
+
code: "flash-cancelled",
|
|
75
|
+
message: "Flash operation was cancelled",
|
|
76
|
+
}));
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
case DfuState.DFU_PROGRESS: {
|
|
80
|
+
if (typeof data.percent === "number") {
|
|
81
|
+
progress(ProgressStage.FullFlashing, data.percent / 100);
|
|
82
|
+
}
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
case DfuState.DFU_FAILED: {
|
|
86
|
+
reject(new DeviceError({
|
|
87
|
+
code: "flash-full-failed",
|
|
88
|
+
message: "Full flash via DFU failed",
|
|
89
|
+
}));
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
default: {
|
|
93
|
+
connection.log(`DFU state: ${state}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
// Note this doesn't await the whole DFU process, just its initialization
|
|
98
|
+
const error = await NordicDfu.startDFU({
|
|
99
|
+
deviceName: device.name,
|
|
100
|
+
deviceAddress: device.deviceId,
|
|
101
|
+
filePath,
|
|
102
|
+
dfuOptions: Capacitor.getPlatform() === "android"
|
|
103
|
+
? {
|
|
104
|
+
...{
|
|
105
|
+
V1: { forceDfu: true },
|
|
106
|
+
V2: {
|
|
107
|
+
unsafeExperimentalButtonlessServiceInSecureDfuEnabled: true,
|
|
108
|
+
disableNotification: true,
|
|
109
|
+
restoreBond: true,
|
|
110
|
+
},
|
|
111
|
+
}[boardVersion],
|
|
112
|
+
startAsForegroundService: false,
|
|
113
|
+
keepBond: true,
|
|
114
|
+
packetReceiptNotificationsEnabled: true,
|
|
115
|
+
}
|
|
116
|
+
: {},
|
|
117
|
+
});
|
|
118
|
+
if (error) {
|
|
119
|
+
connection.error(`DFU Error: ${error.message}`, error);
|
|
120
|
+
reject(new DeviceError({
|
|
121
|
+
code: "flash-full-failed",
|
|
122
|
+
message: error.message || "Full flash via DFU failed",
|
|
123
|
+
}));
|
|
124
|
+
}
|
|
125
|
+
// Final resolution will come from listener callbacks.
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
finally {
|
|
129
|
+
await listener?.remove();
|
|
130
|
+
await cleanupTemporaryFile(connection, filename);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
const createLegacyInitPacketV1 = (appData) => {
|
|
134
|
+
// Legacy DFU init packet structure for micro:bit V1
|
|
135
|
+
// Based on: dev-type 0xFFFF, dev-revision 0xFFFFFFFF, application-version 0xFFFFFFFF, sd-req 0x64
|
|
136
|
+
const buffer = new ArrayBuffer(14);
|
|
137
|
+
const view = new DataView(buffer);
|
|
138
|
+
const uint8View = new Uint8Array(buffer);
|
|
139
|
+
let offset = 0;
|
|
140
|
+
// Device Type (2 bytes, little-endian) - 0xFFFF (wildcard)
|
|
141
|
+
view.setUint16(offset, 0xffff, true);
|
|
142
|
+
offset += 2;
|
|
143
|
+
// Device Revision (2 bytes, little-endian) - 0xFFFF (wildcard, truncated from 0xFFFFFFFF)
|
|
144
|
+
view.setUint16(offset, 0xffff, true);
|
|
145
|
+
offset += 2;
|
|
146
|
+
// Application Version (4 bytes, little-endian) - 0xFFFFFFFF (wildcard)
|
|
147
|
+
view.setUint32(offset, 0xffffffff, true);
|
|
148
|
+
offset += 4;
|
|
149
|
+
// SoftDevice length (2 bytes, little-endian) - 1 (one SoftDevice requirement)
|
|
150
|
+
view.setUint16(offset, 1, true);
|
|
151
|
+
offset += 2;
|
|
152
|
+
// SoftDevice requirement (2 bytes, little-endian) - 0x0064 (S110 v10.0)
|
|
153
|
+
view.setUint16(offset, 0x0064, true);
|
|
154
|
+
offset += 2;
|
|
155
|
+
// CRC-16 of the application (2 bytes, little-endian)
|
|
156
|
+
const crc16 = calculateCRC16(appData);
|
|
157
|
+
view.setUint16(offset, crc16, true);
|
|
158
|
+
return uint8View;
|
|
159
|
+
};
|
|
160
|
+
const calculateCRC16 = (data) => {
|
|
161
|
+
// CRC-16/CCITT-FALSE (polynomial 0x1021, initial value 0xFFFF)
|
|
162
|
+
let crc = 0xffff;
|
|
163
|
+
for (let i = 0; i < data.length; i++) {
|
|
164
|
+
crc ^= data[i] << 8;
|
|
165
|
+
for (let j = 0; j < 8; j++) {
|
|
166
|
+
if (crc & 0x8000) {
|
|
167
|
+
crc = (crc << 1) ^ 0x1021;
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
crc = crc << 1;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return crc & 0xffff;
|
|
175
|
+
};
|
|
176
|
+
const createInitPacketV2 = (appBin) => {
|
|
177
|
+
//typedef struct {
|
|
178
|
+
// uint8_t magic[12]; // identify this struct "microbit_app"
|
|
179
|
+
// uint32_t version; // version of this struct == 1
|
|
180
|
+
// uint32_t app_size; // only used for DFU_FW_TYPE_APPLICATION
|
|
181
|
+
// uint32_t hash_size; // 32 => DFU_HASH_TYPE_SHA256 or zero to bypass hash check
|
|
182
|
+
// uint8_t hash_bytes[32]; // hash of whole DFU download
|
|
183
|
+
//} microbit_dfu_app_t;
|
|
184
|
+
const appSize = appBin.length;
|
|
185
|
+
const magic = "microbit_app";
|
|
186
|
+
const version = 1;
|
|
187
|
+
const hashSize = 0;
|
|
188
|
+
const hash = new Uint8Array(32).fill(0);
|
|
189
|
+
const buffer = new ArrayBuffer(12 + 4 + 4 + 4 + 32); // total: 56 bytes
|
|
190
|
+
const view = new DataView(buffer);
|
|
191
|
+
const uint8View = new Uint8Array(buffer);
|
|
192
|
+
let offset = 0;
|
|
193
|
+
// Write magic string (12 bytes)
|
|
194
|
+
const encoder = new TextEncoder();
|
|
195
|
+
const magicBytes = encoder.encode(magic);
|
|
196
|
+
uint8View.set(magicBytes, offset);
|
|
197
|
+
offset += 12;
|
|
198
|
+
// Write version (4 bytes, little-endian)
|
|
199
|
+
view.setUint32(offset, version, true);
|
|
200
|
+
offset += 4;
|
|
201
|
+
// Write appSize (4 bytes, little-endian)
|
|
202
|
+
view.setUint32(offset, appSize, true);
|
|
203
|
+
offset += 4;
|
|
204
|
+
// Write hashSize (4 bytes, little-endian)
|
|
205
|
+
view.setUint32(offset, hashSize, true);
|
|
206
|
+
offset += 4;
|
|
207
|
+
// Write hash (32 bytes)
|
|
208
|
+
uint8View.set(hash, offset);
|
|
209
|
+
return uint8View;
|
|
210
|
+
};
|
|
211
|
+
//# sourceMappingURL=nordic-dfu.js.map
|