@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.
Files changed (292) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +94 -5
  3. package/build/cjs/accelerometer-service.d.ts +18 -0
  4. package/build/cjs/accelerometer-service.js +105 -0
  5. package/build/cjs/accelerometer-service.js.map +1 -0
  6. package/build/cjs/accelerometer.js +16 -0
  7. package/build/cjs/accelerometer.js.map +1 -0
  8. package/build/{async-util.d.ts → cjs/async-util.d.ts} +9 -0
  9. package/build/cjs/async-util.js +47 -0
  10. package/build/cjs/async-util.js.map +1 -0
  11. package/build/cjs/bluetooth-device-wrapper.d.ts +97 -0
  12. package/build/cjs/bluetooth-device-wrapper.js +486 -0
  13. package/build/cjs/bluetooth-device-wrapper.js.map +1 -0
  14. package/build/{bluetooth-profile.d.ts → cjs/bluetooth-profile.d.ts} +43 -35
  15. package/build/cjs/bluetooth-profile.js +92 -0
  16. package/build/cjs/bluetooth-profile.js.map +1 -0
  17. package/build/cjs/bluetooth.d.ts +112 -0
  18. package/build/cjs/bluetooth.js +458 -0
  19. package/build/cjs/bluetooth.js.map +1 -0
  20. package/build/cjs/board-id.js +81 -0
  21. package/build/cjs/board-id.js.map +1 -0
  22. package/build/cjs/board-serial-info.js +51 -0
  23. package/build/cjs/board-serial-info.js.map +1 -0
  24. package/build/cjs/button-service.d.ts +13 -0
  25. package/build/cjs/button-service.js +66 -0
  26. package/build/cjs/button-service.js.map +1 -0
  27. package/build/cjs/buttons.js +22 -0
  28. package/build/cjs/buttons.js.map +1 -0
  29. package/build/cjs/constants.js +73 -0
  30. package/build/cjs/constants.js.map +1 -0
  31. package/build/cjs/device-information-service.d.ts +6 -0
  32. package/build/cjs/device-information-service.js +34 -0
  33. package/build/cjs/device-information-service.js.map +1 -0
  34. package/build/{device.d.ts → cjs/device.d.ts} +71 -39
  35. package/build/cjs/device.js +147 -0
  36. package/build/cjs/device.js.map +1 -0
  37. package/build/cjs/dfu-service.d.ts +9 -0
  38. package/build/cjs/dfu-service.js +26 -0
  39. package/build/cjs/dfu-service.js.map +1 -0
  40. package/build/{events.d.ts → cjs/events.d.ts} +1 -2
  41. package/build/cjs/events.js +109 -0
  42. package/build/cjs/events.js.map +1 -0
  43. package/build/cjs/flashing/flashing-full.d.ts +14 -0
  44. package/build/cjs/flashing/flashing-full.js +87 -0
  45. package/build/cjs/flashing/flashing-full.js.map +1 -0
  46. package/build/cjs/flashing/flashing-makecode.d.ts +6 -0
  47. package/build/cjs/flashing/flashing-makecode.js +48 -0
  48. package/build/cjs/flashing/flashing-makecode.js.map +1 -0
  49. package/build/cjs/flashing/flashing-partial.d.ts +9 -0
  50. package/build/cjs/flashing/flashing-partial.js +98 -0
  51. package/build/cjs/flashing/flashing-partial.js.map +1 -0
  52. package/build/cjs/flashing/flashing-v1.d.ts +11 -0
  53. package/build/cjs/flashing/flashing-v1.js +24 -0
  54. package/build/cjs/flashing/flashing-v1.js.map +1 -0
  55. package/build/cjs/flashing/nordic-dfu.d.ts +3 -0
  56. package/build/cjs/flashing/nordic-dfu.js +214 -0
  57. package/build/cjs/flashing/nordic-dfu.js.map +1 -0
  58. package/build/cjs/flashing/zip.d.ts +12 -0
  59. package/build/cjs/flashing/zip.js +177 -0
  60. package/build/cjs/flashing/zip.js.map +1 -0
  61. package/build/cjs/hex-flash-data-source.js +26 -0
  62. package/build/cjs/hex-flash-data-source.js.map +1 -0
  63. package/build/cjs/index.d.ts +17 -0
  64. package/build/cjs/index.js +37 -0
  65. package/build/cjs/index.js.map +1 -0
  66. package/build/cjs/led-service.d.ts +18 -0
  67. package/build/cjs/led-service.js +89 -0
  68. package/build/cjs/led-service.js.map +1 -0
  69. package/build/cjs/led.js +3 -0
  70. package/build/cjs/led.js.map +1 -0
  71. package/build/{logging.d.ts → cjs/logging.d.ts} +4 -4
  72. package/build/cjs/logging.js +16 -0
  73. package/build/cjs/logging.js.map +1 -0
  74. package/build/cjs/magnetometer-service.d.ts +18 -0
  75. package/build/cjs/magnetometer-service.js +94 -0
  76. package/build/cjs/magnetometer-service.js.map +1 -0
  77. package/build/cjs/magnetometer.d.ts +9 -0
  78. package/build/cjs/magnetometer.js +16 -0
  79. package/build/cjs/magnetometer.js.map +1 -0
  80. package/build/cjs/package.json +1 -0
  81. package/build/cjs/partial-flashing-service.d.ts +45 -0
  82. package/build/cjs/partial-flashing-service.js +110 -0
  83. package/build/cjs/partial-flashing-service.js.map +1 -0
  84. package/build/cjs/promise-queue.js +78 -0
  85. package/build/cjs/promise-queue.js.map +1 -0
  86. package/build/cjs/serial-events.d.ts +20 -0
  87. package/build/cjs/serial-events.js +69 -0
  88. package/build/cjs/serial-events.js.map +1 -0
  89. package/build/{service-events.d.ts → cjs/service-events.d.ts} +4 -0
  90. package/build/cjs/service-events.js +39 -0
  91. package/build/cjs/service-events.js.map +1 -0
  92. package/build/cjs/setupTests.js.map +1 -0
  93. package/build/cjs/uart-service.d.ts +12 -0
  94. package/build/cjs/uart-service.js +55 -0
  95. package/build/cjs/uart-service.js.map +1 -0
  96. package/build/cjs/uart.d.ts +4 -0
  97. package/build/cjs/uart.js +16 -0
  98. package/build/cjs/uart.js.map +1 -0
  99. package/build/{usb-device-wrapper.d.ts → cjs/usb-device-wrapper.d.ts} +1 -6
  100. package/build/cjs/usb-device-wrapper.js +437 -0
  101. package/build/cjs/usb-device-wrapper.js.map +1 -0
  102. package/build/cjs/usb-partial-flashing-utils.js +133 -0
  103. package/build/cjs/usb-partial-flashing-utils.js.map +1 -0
  104. package/build/{usb-partial-flashing.d.ts → cjs/usb-partial-flashing.d.ts} +3 -5
  105. package/build/cjs/usb-partial-flashing.js +342 -0
  106. package/build/cjs/usb-partial-flashing.js.map +1 -0
  107. package/build/cjs/usb-radio-bridge.d.ts +24 -0
  108. package/build/cjs/usb-radio-bridge.js +515 -0
  109. package/build/cjs/usb-radio-bridge.js.map +1 -0
  110. package/build/cjs/usb-serial-protocol.js +183 -0
  111. package/build/cjs/usb-serial-protocol.js.map +1 -0
  112. package/build/cjs/usb.d.ts +66 -0
  113. package/build/cjs/usb.js +662 -0
  114. package/build/cjs/usb.js.map +1 -0
  115. package/build/esm/accelerometer-service.d.ts +18 -0
  116. package/build/esm/accelerometer-service.js +101 -0
  117. package/build/esm/accelerometer-service.js.map +1 -0
  118. package/build/esm/accelerometer.d.ts +9 -0
  119. package/build/esm/accelerometer.js.map +1 -0
  120. package/build/esm/async-util.d.ts +22 -0
  121. package/build/esm/async-util.js +38 -0
  122. package/build/esm/async-util.js.map +1 -0
  123. package/build/esm/bluetooth-device-wrapper.d.ts +97 -0
  124. package/build/esm/bluetooth-device-wrapper.js +481 -0
  125. package/build/esm/bluetooth-device-wrapper.js.map +1 -0
  126. package/build/esm/bluetooth-profile.d.ts +147 -0
  127. package/build/{bluetooth-profile.js → esm/bluetooth-profile.js} +35 -29
  128. package/build/esm/bluetooth-profile.js.map +1 -0
  129. package/build/esm/bluetooth.d.ts +112 -0
  130. package/build/esm/bluetooth.js +428 -0
  131. package/build/esm/bluetooth.js.map +1 -0
  132. package/build/esm/board-id.d.ts +36 -0
  133. package/build/esm/board-id.js.map +1 -0
  134. package/build/esm/board-serial-info.d.ts +14 -0
  135. package/build/esm/board-serial-info.js.map +1 -0
  136. package/build/esm/button-service.d.ts +13 -0
  137. package/build/esm/button-service.js +62 -0
  138. package/build/esm/button-service.js.map +1 -0
  139. package/build/esm/buttons.d.ts +10 -0
  140. package/build/esm/buttons.js.map +1 -0
  141. package/build/esm/constants.d.ts +48 -0
  142. package/build/esm/constants.js.map +1 -0
  143. package/build/esm/device-information-service.d.ts +6 -0
  144. package/build/esm/device-information-service.js +30 -0
  145. package/build/esm/device-information-service.js.map +1 -0
  146. package/build/esm/device.d.ts +238 -0
  147. package/build/{device.js → esm/device.js} +16 -58
  148. package/build/esm/device.js.map +1 -0
  149. package/build/esm/dfu-service.d.ts +9 -0
  150. package/build/esm/dfu-service.js +22 -0
  151. package/build/esm/dfu-service.js.map +1 -0
  152. package/build/esm/events.d.ts +110 -0
  153. package/build/esm/events.js.map +1 -0
  154. package/build/esm/flashing/flashing-full.d.ts +14 -0
  155. package/build/esm/flashing/flashing-full.js +84 -0
  156. package/build/esm/flashing/flashing-full.js.map +1 -0
  157. package/build/esm/flashing/flashing-makecode.d.ts +6 -0
  158. package/build/esm/flashing/flashing-makecode.js +44 -0
  159. package/build/esm/flashing/flashing-makecode.js.map +1 -0
  160. package/build/esm/flashing/flashing-partial.d.ts +9 -0
  161. package/build/esm/flashing/flashing-partial.js +95 -0
  162. package/build/esm/flashing/flashing-partial.js.map +1 -0
  163. package/build/esm/flashing/flashing-v1.d.ts +11 -0
  164. package/build/esm/flashing/flashing-v1.js +20 -0
  165. package/build/esm/flashing/flashing-v1.js.map +1 -0
  166. package/build/esm/flashing/nordic-dfu.d.ts +3 -0
  167. package/build/esm/flashing/nordic-dfu.js +211 -0
  168. package/build/esm/flashing/nordic-dfu.js.map +1 -0
  169. package/build/esm/flashing/zip.d.ts +12 -0
  170. package/build/esm/flashing/zip.js +174 -0
  171. package/build/esm/flashing/zip.js.map +1 -0
  172. package/build/esm/hex-flash-data-source.d.ts +7 -0
  173. package/build/esm/hex-flash-data-source.js.map +1 -0
  174. package/build/esm/index.d.ts +17 -0
  175. package/build/esm/index.js +12 -0
  176. package/build/esm/index.js.map +1 -0
  177. package/build/esm/led-service.d.ts +18 -0
  178. package/build/esm/led-service.js +85 -0
  179. package/build/esm/led-service.js.map +1 -0
  180. package/build/esm/led.d.ts +6 -0
  181. package/build/esm/led.js.map +1 -0
  182. package/build/esm/logging.d.ts +21 -0
  183. package/build/{logging.js → esm/logging.js} +1 -1
  184. package/build/esm/logging.js.map +1 -0
  185. package/build/esm/magnetometer-service.d.ts +18 -0
  186. package/build/esm/magnetometer-service.js +90 -0
  187. package/build/esm/magnetometer-service.js.map +1 -0
  188. package/build/esm/magnetometer.d.ts +9 -0
  189. package/build/esm/magnetometer.js +12 -0
  190. package/build/esm/magnetometer.js.map +1 -0
  191. package/build/esm/package.json +1 -0
  192. package/build/esm/partial-flashing-service.d.ts +45 -0
  193. package/build/esm/partial-flashing-service.js +106 -0
  194. package/build/esm/partial-flashing-service.js.map +1 -0
  195. package/build/esm/promise-queue.d.ts +27 -0
  196. package/build/esm/promise-queue.js.map +1 -0
  197. package/build/esm/serial-events.d.ts +20 -0
  198. package/build/esm/serial-events.js +61 -0
  199. package/build/esm/serial-events.js.map +1 -0
  200. package/build/esm/service-events.d.ts +17 -0
  201. package/build/{service-events.js → esm/service-events.js} +12 -0
  202. package/build/esm/service-events.js.map +1 -0
  203. package/build/esm/setupTests.d.ts +6 -0
  204. package/build/{setupTests.js.map → esm/setupTests.js.map} +1 -1
  205. package/build/esm/uart-service.d.ts +12 -0
  206. package/build/esm/uart-service.js +51 -0
  207. package/build/esm/uart-service.js.map +1 -0
  208. package/build/esm/uart.d.ts +4 -0
  209. package/build/esm/uart.js +12 -0
  210. package/build/esm/uart.js.map +1 -0
  211. package/build/esm/usb-device-wrapper.d.ts +47 -0
  212. package/build/{usb-device-wrapper.js → esm/usb-device-wrapper.js} +43 -17
  213. package/build/esm/usb-device-wrapper.js.map +1 -0
  214. package/build/esm/usb-partial-flashing-utils.d.ts +17 -0
  215. package/build/esm/usb-partial-flashing-utils.js.map +1 -0
  216. package/build/esm/usb-partial-flashing.d.ts +67 -0
  217. package/build/{usb-partial-flashing.js → esm/usb-partial-flashing.js} +12 -13
  218. package/build/esm/usb-partial-flashing.js.map +1 -0
  219. package/build/esm/usb-radio-bridge.d.ts +24 -0
  220. package/build/{usb-radio-bridge.js → esm/usb-radio-bridge.js} +13 -7
  221. package/build/esm/usb-radio-bridge.js.map +1 -0
  222. package/build/esm/usb-serial-protocol.d.ts +66 -0
  223. package/build/esm/usb-serial-protocol.js.map +1 -0
  224. package/build/esm/usb.d.ts +66 -0
  225. package/build/{usb.js → esm/usb.js} +257 -49
  226. package/build/esm/usb.js.map +1 -0
  227. package/package.json +25 -8
  228. package/typedoc.json +14 -0
  229. package/build/accelerometer-service.d.ts +0 -18
  230. package/build/accelerometer-service.js +0 -102
  231. package/build/accelerometer-service.js.map +0 -1
  232. package/build/accelerometer.js.map +0 -1
  233. package/build/async-util.js +0 -22
  234. package/build/async-util.js.map +0 -1
  235. package/build/bluetooth-device-wrapper.d.ts +0 -57
  236. package/build/bluetooth-device-wrapper.js +0 -433
  237. package/build/bluetooth-device-wrapper.js.map +0 -1
  238. package/build/bluetooth-profile.js.map +0 -1
  239. package/build/bluetooth.d.ts +0 -54
  240. package/build/bluetooth.js +0 -243
  241. package/build/bluetooth.js.map +0 -1
  242. package/build/board-id.js.map +0 -1
  243. package/build/board-serial-info.js.map +0 -1
  244. package/build/button-service.d.ts +0 -13
  245. package/build/button-service.js +0 -76
  246. package/build/button-service.js.map +0 -1
  247. package/build/buttons.js.map +0 -1
  248. package/build/constants.js.map +0 -1
  249. package/build/device.js.map +0 -1
  250. package/build/events.js.map +0 -1
  251. package/build/hex-flash-data-source.js.map +0 -1
  252. package/build/index.d.ts +0 -10
  253. package/build/index.js +0 -8
  254. package/build/index.js.map +0 -1
  255. package/build/led-service.d.ts +0 -20
  256. package/build/led-service.js +0 -116
  257. package/build/led-service.js.map +0 -1
  258. package/build/led.js.map +0 -1
  259. package/build/logging.js.map +0 -1
  260. package/build/promise-queue.js.map +0 -1
  261. package/build/service-events.js.map +0 -1
  262. package/build/usb-device-wrapper.js.map +0 -1
  263. package/build/usb-partial-flashing-utils.js.map +0 -1
  264. package/build/usb-partial-flashing.js.map +0 -1
  265. package/build/usb-radio-bridge.d.ts +0 -41
  266. package/build/usb-radio-bridge.js.map +0 -1
  267. package/build/usb-serial-protocol.js.map +0 -1
  268. package/build/usb.d.ts +0 -54
  269. package/build/usb.js.map +0 -1
  270. package/vite.config.ts +0 -34
  271. /package/build/{accelerometer.d.ts → cjs/accelerometer.d.ts} +0 -0
  272. /package/build/{board-id.d.ts → cjs/board-id.d.ts} +0 -0
  273. /package/build/{board-serial-info.d.ts → cjs/board-serial-info.d.ts} +0 -0
  274. /package/build/{buttons.d.ts → cjs/buttons.d.ts} +0 -0
  275. /package/build/{constants.d.ts → cjs/constants.d.ts} +0 -0
  276. /package/build/{hex-flash-data-source.d.ts → cjs/hex-flash-data-source.d.ts} +0 -0
  277. /package/build/{led.d.ts → cjs/led.d.ts} +0 -0
  278. /package/build/{promise-queue.d.ts → cjs/promise-queue.d.ts} +0 -0
  279. /package/build/{setupTests.d.ts → cjs/setupTests.d.ts} +0 -0
  280. /package/build/{usb-partial-flashing-utils.d.ts → cjs/usb-partial-flashing-utils.d.ts} +0 -0
  281. /package/build/{usb-serial-protocol.d.ts → cjs/usb-serial-protocol.d.ts} +0 -0
  282. /package/build/{accelerometer.js → esm/accelerometer.js} +0 -0
  283. /package/build/{board-id.js → esm/board-id.js} +0 -0
  284. /package/build/{board-serial-info.js → esm/board-serial-info.js} +0 -0
  285. /package/build/{buttons.js → esm/buttons.js} +0 -0
  286. /package/build/{constants.js → esm/constants.js} +0 -0
  287. /package/build/{events.js → esm/events.js} +0 -0
  288. /package/build/{hex-flash-data-source.js → esm/hex-flash-data-source.js} +0 -0
  289. /package/build/{led.js → esm/led.js} +0 -0
  290. /package/build/{promise-queue.js → esm/promise-queue.js} +0 -0
  291. /package/build/{usb-partial-flashing-utils.js → esm/usb-partial-flashing-utils.js} +0 -0
  292. /package/build/{usb-serial-protocol.js → esm/usb-serial-protocol.js} +0 -0
@@ -0,0 +1,662 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.applyDeviceFilters = exports.createWebUSBConnection = exports.DeviceSelectionMode = exports.isChromeOS105 = void 0;
4
+ /**
5
+ * (c) 2021, Micro:bit Educational Foundation and contributors
6
+ *
7
+ * SPDX-License-Identifier: MIT
8
+ */
9
+ const async_util_js_1 = require("./async-util.js");
10
+ const device_js_1 = require("./device.js");
11
+ const events_js_1 = require("./events.js");
12
+ const logging_js_1 = require("./logging.js");
13
+ const promise_queue_js_1 = require("./promise-queue.js");
14
+ const serial_events_js_1 = require("./serial-events.js");
15
+ const usb_device_wrapper_js_1 = require("./usb-device-wrapper.js");
16
+ const usb_partial_flashing_js_1 = require("./usb-partial-flashing.js");
17
+ // Temporary workaround for ChromeOS 105 bug.
18
+ // See https://bugs.chromium.org/p/chromium/issues/detail?id=1363712&q=usb&can=2
19
+ const isChromeOS105 = () => {
20
+ const userAgent = navigator.userAgent;
21
+ return /CrOS/.test(userAgent) && /Chrome\/105\b/.test(userAgent);
22
+ };
23
+ exports.isChromeOS105 = isChromeOS105;
24
+ const defaultFilters = [{ vendorId: 0x0d28, productId: 0x0204 }];
25
+ var DeviceSelectionMode;
26
+ (function (DeviceSelectionMode) {
27
+ /**
28
+ * Attempts to connect to known device, otherwise asks which device to
29
+ * connect to.
30
+ */
31
+ DeviceSelectionMode["AlwaysAsk"] = "AlwaysAsk";
32
+ /**
33
+ * Attempts to connect to known device, otherwise attempts to connect to any
34
+ * allowed devices. If that fails, asks which device to connect to.
35
+ */
36
+ DeviceSelectionMode["UseAnyAllowed"] = "UseAnyAllowed";
37
+ })(DeviceSelectionMode || (exports.DeviceSelectionMode = DeviceSelectionMode = {}));
38
+ /**
39
+ * A WebUSB connection factory.
40
+ */
41
+ const createWebUSBConnection = (options) => new MicrobitWebUSBConnectionImpl(options);
42
+ exports.createWebUSBConnection = createWebUSBConnection;
43
+ /**
44
+ * A WebUSB connection to a micro:bit device.
45
+ */
46
+ class MicrobitWebUSBConnectionImpl extends events_js_1.TypedEventTarget {
47
+ constructor(options = {}) {
48
+ super();
49
+ Object.defineProperty(this, "status", {
50
+ enumerable: true,
51
+ configurable: true,
52
+ writable: true,
53
+ value: navigator.usb && !(0, exports.isChromeOS105)()
54
+ ? device_js_1.ConnectionStatus.NO_AUTHORIZED_DEVICE
55
+ : device_js_1.ConnectionStatus.NOT_SUPPORTED
56
+ });
57
+ Object.defineProperty(this, "exclusionFilters", {
58
+ enumerable: true,
59
+ configurable: true,
60
+ writable: true,
61
+ value: void 0
62
+ });
63
+ /**
64
+ * The USB device we last connected to.
65
+ * Cleared if it is disconnected.
66
+ */
67
+ Object.defineProperty(this, "device", {
68
+ enumerable: true,
69
+ configurable: true,
70
+ writable: true,
71
+ value: void 0
72
+ });
73
+ /**
74
+ * The connection to the device.
75
+ */
76
+ Object.defineProperty(this, "connection", {
77
+ enumerable: true,
78
+ configurable: true,
79
+ writable: true,
80
+ value: void 0
81
+ });
82
+ Object.defineProperty(this, "serialState", {
83
+ enumerable: true,
84
+ configurable: true,
85
+ writable: true,
86
+ value: false
87
+ });
88
+ Object.defineProperty(this, "serialStateChangeQueue", {
89
+ enumerable: true,
90
+ configurable: true,
91
+ writable: true,
92
+ value: new promise_queue_js_1.PromiseQueue()
93
+ });
94
+ Object.defineProperty(this, "serialListener", {
95
+ enumerable: true,
96
+ configurable: true,
97
+ writable: true,
98
+ value: (data) => {
99
+ this.dispatchTypedEvent("serialdata", new serial_events_js_1.SerialDataEvent(data));
100
+ }
101
+ });
102
+ Object.defineProperty(this, "flashing", {
103
+ enumerable: true,
104
+ configurable: true,
105
+ writable: true,
106
+ value: false
107
+ });
108
+ Object.defineProperty(this, "disconnectAfterFlash", {
109
+ enumerable: true,
110
+ configurable: true,
111
+ writable: true,
112
+ value: false
113
+ });
114
+ Object.defineProperty(this, "visibilityReconnect", {
115
+ enumerable: true,
116
+ configurable: true,
117
+ writable: true,
118
+ value: false
119
+ });
120
+ Object.defineProperty(this, "visibilityChangeListener", {
121
+ enumerable: true,
122
+ configurable: true,
123
+ writable: true,
124
+ value: () => {
125
+ if (document.visibilityState === "visible") {
126
+ if (this.visibilityReconnect &&
127
+ this.status !== device_js_1.ConnectionStatus.CONNECTED) {
128
+ this.disconnectAfterFlash = false;
129
+ this.visibilityReconnect = false;
130
+ if (!this.flashing) {
131
+ this.log("Reconnecting visible tab");
132
+ this.connect();
133
+ }
134
+ }
135
+ }
136
+ else {
137
+ if (!this.unloading && this.status === device_js_1.ConnectionStatus.CONNECTED) {
138
+ if (!this.flashing) {
139
+ this.log("Disconnecting hidden tab");
140
+ this.disconnect().then(() => {
141
+ this.visibilityReconnect = true;
142
+ });
143
+ }
144
+ else {
145
+ this.log("Scheduling disconnect of hidden tab for after flash");
146
+ this.disconnectAfterFlash = true;
147
+ }
148
+ }
149
+ }
150
+ }
151
+ });
152
+ Object.defineProperty(this, "unloading", {
153
+ enumerable: true,
154
+ configurable: true,
155
+ writable: true,
156
+ value: false
157
+ });
158
+ Object.defineProperty(this, "beforeUnloadListener", {
159
+ enumerable: true,
160
+ configurable: true,
161
+ writable: true,
162
+ value: () => {
163
+ // If serial is in progress when the page unloads with V1 DAPLink 0254 or V2 0255
164
+ // then it'll fail to reconnect with mismatched command/response errors.
165
+ // Try hard to disconnect as a workaround.
166
+ // https://github.com/microbit-foundation/python-editor-v3/issues/89
167
+ this.unloading = true;
168
+ this.stopSerialInternal();
169
+ // The user might stay on the page if they have unsaved changes and there's another beforeunload listener.
170
+ window.addEventListener("focus", () => {
171
+ const assumePageIsStayingOpenDelay = 1000;
172
+ setTimeout(() => {
173
+ if (this.status === device_js_1.ConnectionStatus.CONNECTED) {
174
+ this.unloading = false;
175
+ if (this.addedListeners.serialdata) {
176
+ this.startSerialInternal();
177
+ }
178
+ }
179
+ }, assumePageIsStayingOpenDelay);
180
+ }, { once: true });
181
+ }
182
+ });
183
+ Object.defineProperty(this, "logging", {
184
+ enumerable: true,
185
+ configurable: true,
186
+ writable: true,
187
+ value: void 0
188
+ });
189
+ Object.defineProperty(this, "deviceSelectionMode", {
190
+ enumerable: true,
191
+ configurable: true,
192
+ writable: true,
193
+ value: void 0
194
+ });
195
+ Object.defineProperty(this, "addedListeners", {
196
+ enumerable: true,
197
+ configurable: true,
198
+ writable: true,
199
+ value: {
200
+ serialdata: 0,
201
+ }
202
+ });
203
+ Object.defineProperty(this, "handleDisconnect", {
204
+ enumerable: true,
205
+ configurable: true,
206
+ writable: true,
207
+ value: (event) => {
208
+ if (event.device === this.device) {
209
+ this.connection = undefined;
210
+ this.device = undefined;
211
+ this.setStatus(device_js_1.ConnectionStatus.NO_AUTHORIZED_DEVICE);
212
+ }
213
+ }
214
+ });
215
+ this.logging = options.logging || new logging_js_1.ConsoleLogging();
216
+ this.deviceSelectionMode =
217
+ options.deviceSelectionMode || DeviceSelectionMode.AlwaysAsk;
218
+ }
219
+ log(v) {
220
+ this.logging.log(v);
221
+ }
222
+ async initialize() {
223
+ if (navigator.usb) {
224
+ navigator.usb.addEventListener("disconnect", this.handleDisconnect);
225
+ }
226
+ if (typeof window !== "undefined") {
227
+ window.addEventListener("beforeunload", this.beforeUnloadListener);
228
+ if (window.document) {
229
+ window.document.addEventListener("visibilitychange", this.visibilityChangeListener);
230
+ }
231
+ }
232
+ }
233
+ dispose() {
234
+ if (navigator.usb) {
235
+ navigator.usb.removeEventListener("disconnect", this.handleDisconnect);
236
+ }
237
+ if (typeof window !== "undefined") {
238
+ window.removeEventListener("beforeunload", this.beforeUnloadListener);
239
+ if (window.document) {
240
+ window.document.removeEventListener("visibilitychange", this.visibilityChangeListener);
241
+ }
242
+ }
243
+ }
244
+ setRequestDeviceExclusionFilters(exclusionFilters) {
245
+ this.exclusionFilters = exclusionFilters;
246
+ }
247
+ async connect(options) {
248
+ await this.withEnrichedErrors(async () => {
249
+ await this.connectInternal(options?.progress);
250
+ return this.status;
251
+ });
252
+ }
253
+ getDeviceId() {
254
+ return this.connection?.deviceId;
255
+ }
256
+ getDevice() {
257
+ return this.device;
258
+ }
259
+ getBoardVersion() {
260
+ return this.connection?.boardSerialInfo?.id.toBoardVersion();
261
+ }
262
+ async flash(dataSource, options) {
263
+ this.flashing = true;
264
+ try {
265
+ const startTime = new Date().getTime();
266
+ await this.withEnrichedErrors(() => this.flashInternal(dataSource, options));
267
+ this.dispatchTypedEvent("flash", new serial_events_js_1.FlashEvent());
268
+ const flashTime = new Date().getTime() - startTime;
269
+ this.logging.event({
270
+ type: "WebUSB-time",
271
+ detail: {
272
+ flashTime,
273
+ },
274
+ });
275
+ this.logging.log("Flash complete");
276
+ }
277
+ finally {
278
+ this.flashing = false;
279
+ }
280
+ }
281
+ async flashInternal(dataSource, options = {}) {
282
+ const partial = options.partial ?? true;
283
+ const progress = rateLimitProgress(options.minimumProgressIncrement ?? 0.0025, options.progress || (() => { }));
284
+ this.log("Stopping serial before flash");
285
+ await this.stopSerialInternal();
286
+ this.log("Reconnecting before flash");
287
+ await this.connectInternal(progress);
288
+ if (!this.connection) {
289
+ throw new device_js_1.DeviceError({
290
+ code: "device-disconnected",
291
+ message: "Must be connected now",
292
+ });
293
+ }
294
+ progress(device_js_1.ProgressStage.Initializing, undefined);
295
+ const boardId = this.connection.boardSerialInfo.id;
296
+ const boardVersion = boardId.toBoardVersion();
297
+ const data = await dataSource(boardVersion);
298
+ const flashing = new usb_partial_flashing_js_1.PartialFlashing(this.connection, this.logging, boardVersion);
299
+ let wasPartial = false;
300
+ try {
301
+ if (partial) {
302
+ wasPartial = await flashing.flashAsync(data, progress);
303
+ }
304
+ else {
305
+ await flashing.fullFlashAsync(data, progress);
306
+ }
307
+ }
308
+ finally {
309
+ progress(wasPartial ? device_js_1.ProgressStage.PartialFlashing : device_js_1.ProgressStage.FullFlashing, undefined);
310
+ if (this.disconnectAfterFlash) {
311
+ this.log("Disconnecting after flash due to tab visibility");
312
+ this.disconnectAfterFlash = false;
313
+ await this.disconnect();
314
+ this.visibilityReconnect = true;
315
+ }
316
+ else {
317
+ if (this.addedListeners.serialdata) {
318
+ this.log("Reinstating serial after flash");
319
+ if (this.connection.daplink) {
320
+ await this.connection.daplink.connect();
321
+ await this.startSerialInternal();
322
+ }
323
+ }
324
+ }
325
+ }
326
+ }
327
+ async startSerialInternal() {
328
+ return this.serialStateChangeQueue.add(async () => {
329
+ if (!this.connection || this.serialState) {
330
+ return;
331
+ }
332
+ this.log("Starting serial");
333
+ this.serialState = true;
334
+ this.connection
335
+ .startSerial(this.serialListener)
336
+ .then(() => {
337
+ this.log("Finished listening for serial data");
338
+ })
339
+ .catch((e) => {
340
+ this.dispatchTypedEvent("serialerror", new serial_events_js_1.SerialErrorEvent(e));
341
+ })
342
+ .finally(() => {
343
+ this.serialState = false;
344
+ });
345
+ });
346
+ }
347
+ async stopSerialInternal() {
348
+ return this.serialStateChangeQueue.add(async () => {
349
+ if (!this.connection || !this.serialState) {
350
+ return;
351
+ }
352
+ this.connection.stopSerial(this.serialListener);
353
+ this.dispatchTypedEvent("serialreset", new serial_events_js_1.SerialResetEvent());
354
+ });
355
+ }
356
+ async disconnect(quiet) {
357
+ try {
358
+ if (this.connection) {
359
+ await this.stopSerialInternal();
360
+ await this.connection.disconnectAsync();
361
+ }
362
+ }
363
+ catch (e) {
364
+ if (!quiet) {
365
+ this.log("Error during disconnection:\r\n" + e);
366
+ this.logging.event({
367
+ type: "WebUSB-error",
368
+ message: "error-disconnecting",
369
+ });
370
+ }
371
+ }
372
+ finally {
373
+ this.connection = undefined;
374
+ this.setStatus(device_js_1.ConnectionStatus.DISCONNECTED);
375
+ if (!quiet) {
376
+ this.logging.log("Disconnection complete");
377
+ this.logging.event({
378
+ type: "WebUSB-info",
379
+ message: "disconnected",
380
+ });
381
+ }
382
+ }
383
+ }
384
+ setStatus(newStatus) {
385
+ this.status = newStatus;
386
+ this.visibilityReconnect = false;
387
+ this.log("USB connection status " + newStatus);
388
+ this.dispatchTypedEvent("status", new device_js_1.ConnectionStatusEvent(newStatus));
389
+ }
390
+ async withEnrichedErrors(f) {
391
+ try {
392
+ return await f();
393
+ }
394
+ catch (e) {
395
+ if (e instanceof device_js_1.FlashDataError) {
396
+ throw e;
397
+ }
398
+ if (e instanceof device_js_1.DeviceError) {
399
+ throw e;
400
+ }
401
+ // Log error to console for feedback
402
+ this.log("An error occurred whilst attempting to use WebUSB.");
403
+ this.log("Details of the error can be found below, and may be useful when trying to replicate and debug the error.");
404
+ this.log(e);
405
+ // Disconnect from the microbit.
406
+ // Any new connection reallocates all the internals.
407
+ // Use the top-level API so any listeners reflect that we're disconnected.
408
+ await this.disconnect(true);
409
+ const enriched = enrichedError(e);
410
+ // Sanitise error message, replace all special chars with '-', if last char is '-' remove it
411
+ const errorMessage = e.message
412
+ ? e.message.replace(/\W+/g, "-").replace(/\W$/, "").toLowerCase()
413
+ : "";
414
+ this.logging.event({
415
+ type: "WebUSB-error",
416
+ message: e.code + "/" + errorMessage,
417
+ });
418
+ throw enriched;
419
+ }
420
+ }
421
+ serialWrite(data) {
422
+ return this.withEnrichedErrors(async () => {
423
+ if (this.connection) {
424
+ // Using WebUSB/DAPJs we're limited to 64 byte packet size with a two byte header.
425
+ // https://github.com/microbit-foundation/python-editor-v3/issues/215
426
+ const maxSerialWrite = 62;
427
+ let start = 0;
428
+ while (start < data.length) {
429
+ const end = Math.min(start + maxSerialWrite, data.length);
430
+ const chunkData = data.slice(start, end);
431
+ await this.connection.daplink.serialWrite(chunkData);
432
+ start = end;
433
+ }
434
+ }
435
+ });
436
+ }
437
+ async softwareReset() {
438
+ return this.serialStateChangeQueue.add(async () => await this.connection?.softwareReset());
439
+ }
440
+ async clearDevice() {
441
+ await this.disconnect();
442
+ this.device = undefined;
443
+ this.setStatus(device_js_1.ConnectionStatus.NO_AUTHORIZED_DEVICE);
444
+ }
445
+ async connectInternal(progress) {
446
+ const reportProgress = progress ?? (() => { });
447
+ if (!this.connection && this.device) {
448
+ reportProgress(device_js_1.ProgressStage.Connecting);
449
+ this.connection = new usb_device_wrapper_js_1.DAPWrapper(this.device, this.logging);
450
+ await (0, async_util_js_1.withTimeout)(this.connection.reconnectAsync(), 10_000);
451
+ }
452
+ else if (!this.connection) {
453
+ await this.connectWithOtherDevice(reportProgress);
454
+ }
455
+ else {
456
+ reportProgress(device_js_1.ProgressStage.Connecting);
457
+ await (0, async_util_js_1.withTimeout)(this.connection.reconnectAsync(), 10_000);
458
+ }
459
+ if (this.addedListeners.serialdata && !this.flashing) {
460
+ this.startSerialInternal();
461
+ }
462
+ this.setStatus(device_js_1.ConnectionStatus.CONNECTED);
463
+ }
464
+ async connectWithOtherDevice(progress) {
465
+ if (this.deviceSelectionMode === DeviceSelectionMode.UseAnyAllowed) {
466
+ await this.attemptConnectAllowedDevices();
467
+ }
468
+ if (!this.connection) {
469
+ progress(device_js_1.ProgressStage.FindingDevice);
470
+ this.device = await this.chooseDevice();
471
+ progress(device_js_1.ProgressStage.Connecting);
472
+ this.connection = new usb_device_wrapper_js_1.DAPWrapper(this.device, this.logging);
473
+ await (0, async_util_js_1.withTimeout)(this.connection.reconnectAsync(), 10_000);
474
+ }
475
+ }
476
+ // Based on: https://github.com/microsoft/pxt/blob/ab97a2422879824c730f009b15d4bf446b0e8547/pxtlib/webusb.ts#L361
477
+ async attemptConnectAllowedDevices() {
478
+ const pairedDevices = await this.getFilteredAllowedDevices();
479
+ for (const device of pairedDevices) {
480
+ const connection = await this.attemptDeviceConnection(device);
481
+ if (connection) {
482
+ this.device = device;
483
+ this.connection = connection;
484
+ return;
485
+ }
486
+ }
487
+ }
488
+ // Based on: https://github.com/microsoft/pxt/blob/ab97a2422879824c730f009b15d4bf446b0e8547/pxtlib/webusb.ts#L530
489
+ async getFilteredAllowedDevices() {
490
+ this.log("Retrieving previously paired USB devices");
491
+ const devices = await navigator.usb?.getDevices();
492
+ if (devices === undefined) {
493
+ return [];
494
+ }
495
+ const filteredDevices = devices.filter((device) => (0, exports.applyDeviceFilters)(device, defaultFilters, this.exclusionFilters ?? []));
496
+ return filteredDevices;
497
+ }
498
+ async attemptDeviceConnection(device) {
499
+ this.log(`Attempting connection to: ${device.manufacturerName} ${device.productName}`);
500
+ this.log(`Serial number: ${device.serialNumber}`);
501
+ const connection = new usb_device_wrapper_js_1.DAPWrapper(device, this.logging);
502
+ await (0, async_util_js_1.withTimeout)(connection.reconnectAsync(), 10_000);
503
+ return connection;
504
+ }
505
+ async chooseDevice() {
506
+ this.dispatchTypedEvent("beforerequestdevice", new device_js_1.BeforeRequestDevice());
507
+ try {
508
+ this.device = await navigator.usb.requestDevice({
509
+ exclusionFilters: this.exclusionFilters,
510
+ filters: defaultFilters,
511
+ });
512
+ }
513
+ finally {
514
+ this.dispatchTypedEvent("afterrequestdevice", new device_js_1.AfterRequestDevice());
515
+ }
516
+ return this.device;
517
+ }
518
+ eventActivated(type) {
519
+ switch (type) {
520
+ case "serialdata": {
521
+ // Prevent starting serial if already started and when flashing.
522
+ if (!this.addedListeners.serialdata && !this.flashing) {
523
+ this.startSerialInternal();
524
+ }
525
+ this.addedListeners.serialdata++;
526
+ break;
527
+ }
528
+ }
529
+ }
530
+ async eventDeactivated(type) {
531
+ switch (type) {
532
+ case "serialdata": {
533
+ this.addedListeners.serialdata--;
534
+ if (!this.addedListeners.serialdata) {
535
+ this.stopSerialInternal();
536
+ }
537
+ break;
538
+ }
539
+ }
540
+ }
541
+ }
542
+ /**
543
+ * Applying WebUSB device filter. Exported for testing.
544
+ * Based on: https://wicg.github.io/webusb/#enumeration
545
+ */
546
+ const applyDeviceFilters = (device, filters, exclusionFilters) => {
547
+ return ((filters.length === 0 ||
548
+ filters.some((filter) => matchFilter(device, filter))) &&
549
+ (exclusionFilters.length === 0 ||
550
+ exclusionFilters.every((filter) => !matchFilter(device, filter))));
551
+ };
552
+ exports.applyDeviceFilters = applyDeviceFilters;
553
+ const matchFilter = (device, filter) => {
554
+ if (filter.vendorId && device.vendorId !== filter.vendorId) {
555
+ return false;
556
+ }
557
+ if (filter.productId && device.productId !== filter.productId) {
558
+ return false;
559
+ }
560
+ if (filter.serialNumber && device.serialNumber !== filter.serialNumber) {
561
+ return false;
562
+ }
563
+ return hasMatchingInterface(device, filter);
564
+ };
565
+ const hasMatchingInterface = (device, filter) => {
566
+ if (filter.classCode === undefined &&
567
+ filter.subclassCode === undefined &&
568
+ filter.protocolCode === undefined) {
569
+ return true;
570
+ }
571
+ if (!device.configuration?.interfaces) {
572
+ return false;
573
+ }
574
+ return device.configuration.interfaces.some((configInterface) => {
575
+ return configInterface.alternates?.some((alternate) => {
576
+ const classCodeNotMatch = filter.classCode !== undefined &&
577
+ alternate.interfaceClass !== filter.classCode;
578
+ const subClassCodeNotMatch = filter.subclassCode !== undefined &&
579
+ alternate.interfaceSubclass !== filter.subclassCode;
580
+ const protocolCodeNotMatch = filter.protocolCode !== undefined &&
581
+ alternate.interfaceProtocol !== filter.protocolCode;
582
+ return (!classCodeNotMatch || !subClassCodeNotMatch || !protocolCodeNotMatch);
583
+ });
584
+ });
585
+ };
586
+ const genericErrorSuggestingReconnect = (e) => new device_js_1.DeviceError({
587
+ code: "reconnect-microbit",
588
+ message: e.message,
589
+ });
590
+ // tslint:disable-next-line: no-any
591
+ const enrichedError = (err) => {
592
+ if (err instanceof device_js_1.DeviceError) {
593
+ return err;
594
+ }
595
+ if (err instanceof async_util_js_1.TimeoutError) {
596
+ return new device_js_1.DeviceError({
597
+ code: "timeout-error",
598
+ message: err.message,
599
+ });
600
+ }
601
+ switch (typeof err) {
602
+ case "object":
603
+ // We might get Error objects as Promise rejection arguments
604
+ if (!err.message && err.promise && err.reason) {
605
+ err = err.reason;
606
+ }
607
+ // This is somewhat fragile but worth it for scenario specific errors.
608
+ // These messages changed to be prefixed in 2023 so we've relaxed the checks.
609
+ if (/No valid interfaces found/.test(err.message)) {
610
+ // This comes from DAPjs's WebUSB open.
611
+ return new device_js_1.DeviceError({
612
+ code: "update-req",
613
+ message: err.message,
614
+ });
615
+ }
616
+ else if (/No device selected/.test(err.message)) {
617
+ return new device_js_1.DeviceError({
618
+ code: "no-device-selected",
619
+ message: err.message,
620
+ });
621
+ }
622
+ else if (/Unable to claim interface/.test(err.message)) {
623
+ return new device_js_1.DeviceError({
624
+ code: "clear-connect",
625
+ message: err.message,
626
+ });
627
+ }
628
+ else if (err.name === "device-disconnected") {
629
+ return new device_js_1.DeviceError({
630
+ code: "device-disconnected",
631
+ message: err.message,
632
+ });
633
+ }
634
+ else {
635
+ // Unhandled error. User will need to reconnect their micro:bit
636
+ return genericErrorSuggestingReconnect(err);
637
+ }
638
+ case "string": {
639
+ // Caught a string. Example case: "Flash error" from DAPjs
640
+ return genericErrorSuggestingReconnect(err);
641
+ }
642
+ default: {
643
+ return genericErrorSuggestingReconnect(err);
644
+ }
645
+ }
646
+ };
647
+ const rateLimitProgress = (minimumProgressIncrement, callback) => {
648
+ let lastCallValue = -1;
649
+ let lastStage;
650
+ return (stage, value) => {
651
+ if (lastStage !== stage ||
652
+ value === undefined ||
653
+ value === 0 ||
654
+ value === 1 ||
655
+ value >= lastCallValue + minimumProgressIncrement) {
656
+ lastStage = stage;
657
+ lastCallValue = value ?? -1;
658
+ callback(stage, value);
659
+ }
660
+ };
661
+ };
662
+ //# sourceMappingURL=usb.js.map