@yume-chan/adb-daemon-webusb 0.0.24 → 1.0.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/CHANGELOG.md +37 -1
- package/README.md +6 -3
- package/esm/device.d.ts +11 -14
- package/esm/device.d.ts.map +1 -1
- package/esm/device.js +43 -52
- package/esm/device.js.map +1 -1
- package/esm/index.d.ts +1 -1
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +1 -1
- package/esm/index.js.map +1 -1
- package/esm/manager.d.ts +6 -25
- package/esm/manager.d.ts.map +1 -1
- package/esm/manager.js +30 -60
- package/esm/manager.js.map +1 -1
- package/esm/observer.d.ts +17 -0
- package/esm/observer.d.ts.map +1 -0
- package/esm/observer.js +54 -0
- package/esm/observer.js.map +1 -0
- package/esm/utils.d.ts +22 -5
- package/esm/utils.d.ts.map +1 -1
- package/esm/utils.js +76 -5
- package/esm/utils.js.map +1 -1
- package/package.json +13 -9
- package/src/device.ts +53 -65
- package/src/index.ts +1 -1
- package/src/manager.ts +49 -75
- package/src/observer.ts +90 -0
- package/src/utils.ts +142 -18
- package/tsconfig.build.json +2 -13
- package/tsconfig.build.tsbuildinfo +1 -1
- package/CHANGELOG.json +0 -199
- package/esm/watcher.d.ts +0 -7
- package/esm/watcher.d.ts.map +0 -1
- package/esm/watcher.js +0 -21
- package/esm/watcher.js.map +0 -1
- package/src/watcher.ts +0 -28
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { DeviceObserver } from "@yume-chan/adb";
|
|
2
|
+
import { AdbDaemonWebUsbDevice } from "./device.js";
|
|
3
|
+
import type { AdbDaemonWebUsbDeviceManager } from "./manager.js";
|
|
4
|
+
/**
|
|
5
|
+
* A watcher that listens for new WebUSB devices and notifies the callback when
|
|
6
|
+
* a new device is connected or disconnected.
|
|
7
|
+
*/
|
|
8
|
+
export declare class AdbDaemonWebUsbDeviceObserver implements DeviceObserver<AdbDaemonWebUsbDevice> {
|
|
9
|
+
#private;
|
|
10
|
+
onDeviceAdd: import("@yume-chan/event").AddEventListener<AdbDaemonWebUsbDevice[], unknown>;
|
|
11
|
+
onDeviceRemove: import("@yume-chan/event").AddEventListener<AdbDaemonWebUsbDevice[], unknown>;
|
|
12
|
+
onListChange: import("@yume-chan/event").AddEventListener<AdbDaemonWebUsbDevice[], unknown>;
|
|
13
|
+
current: AdbDaemonWebUsbDevice[];
|
|
14
|
+
constructor(usb: USB, options?: AdbDaemonWebUsbDeviceManager.RequestDeviceOptions);
|
|
15
|
+
stop(): void;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=observer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observer.d.ts","sourceRoot":"","sources":["../src/observer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGrD,OAAO,EACH,qBAAqB,EAExB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,cAAc,CAAC;AAIjE;;;GAGG;AACH,qBAAa,6BACT,YAAW,cAAc,CAAC,qBAAqB,CAAC;;IAOhD,WAAW,gFAA2B;IAGtC,cAAc,gFAA8B;IAG5C,YAAY,gFAA4B;IAExC,OAAO,EAAE,qBAAqB,EAAE,CAAM;gBAGlC,GAAG,EAAE,GAAG,EACR,OAAO,GAAE,4BAA4B,CAAC,oBAAyB;IA2CnE,IAAI,IAAI,IAAI;CAWf"}
|
package/esm/observer.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { EventEmitter } from "@yume-chan/event";
|
|
2
|
+
import { AdbDaemonWebUsbDevice, mergeDefaultAdbInterfaceFilter, } from "./device.js";
|
|
3
|
+
import { matchFilters } from "./utils.js";
|
|
4
|
+
/**
|
|
5
|
+
* A watcher that listens for new WebUSB devices and notifies the callback when
|
|
6
|
+
* a new device is connected or disconnected.
|
|
7
|
+
*/
|
|
8
|
+
export class AdbDaemonWebUsbDeviceObserver {
|
|
9
|
+
#filters;
|
|
10
|
+
#exclusionFilters;
|
|
11
|
+
#usbManager;
|
|
12
|
+
#onDeviceAdd = new EventEmitter();
|
|
13
|
+
onDeviceAdd = this.#onDeviceAdd.event;
|
|
14
|
+
#onDeviceRemove = new EventEmitter();
|
|
15
|
+
onDeviceRemove = this.#onDeviceRemove.event;
|
|
16
|
+
#onListChange = new EventEmitter();
|
|
17
|
+
onListChange = this.#onListChange.event;
|
|
18
|
+
current = [];
|
|
19
|
+
constructor(usb, options = {}) {
|
|
20
|
+
this.#filters = mergeDefaultAdbInterfaceFilter(options.filters);
|
|
21
|
+
this.#exclusionFilters = options.exclusionFilters;
|
|
22
|
+
this.#usbManager = usb;
|
|
23
|
+
this.#usbManager.addEventListener("connect", this.#handleConnect);
|
|
24
|
+
this.#usbManager.addEventListener("disconnect", this.#handleDisconnect);
|
|
25
|
+
}
|
|
26
|
+
#handleConnect = (e) => {
|
|
27
|
+
const interface_ = matchFilters(e.device, this.#filters, this.#exclusionFilters);
|
|
28
|
+
if (!interface_) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const device = new AdbDaemonWebUsbDevice(e.device, interface_, this.#usbManager);
|
|
32
|
+
this.#onDeviceAdd.fire([device]);
|
|
33
|
+
this.current.push(device);
|
|
34
|
+
this.#onListChange.fire(this.current);
|
|
35
|
+
};
|
|
36
|
+
#handleDisconnect = (e) => {
|
|
37
|
+
const index = this.current.findIndex((device) => device.raw === e.device);
|
|
38
|
+
if (index !== -1) {
|
|
39
|
+
const device = this.current[index];
|
|
40
|
+
this.#onDeviceRemove.fire([device]);
|
|
41
|
+
this.current[index] = this.current[this.current.length - 1];
|
|
42
|
+
this.current.length -= 1;
|
|
43
|
+
this.#onListChange.fire(this.current);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
stop() {
|
|
47
|
+
this.#usbManager.removeEventListener("connect", this.#handleConnect);
|
|
48
|
+
this.#usbManager.removeEventListener("disconnect", this.#handleDisconnect);
|
|
49
|
+
this.#onDeviceAdd.dispose();
|
|
50
|
+
this.#onDeviceRemove.dispose();
|
|
51
|
+
this.#onListChange.dispose();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=observer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observer.js","sourceRoot":"","sources":["../src/observer.ts"],"names":[],"mappings":"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"}
|
package/esm/utils.d.ts
CHANGED
|
@@ -1,14 +1,31 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
1
|
+
export declare function isErrorName(e: unknown, name: string): e is Error;
|
|
2
|
+
export type PickNonNullable<T, K extends keyof T> = {
|
|
3
|
+
[P in K]-?: NonNullable<T[P]>;
|
|
4
|
+
};
|
|
3
5
|
/**
|
|
4
6
|
* `classCode`, `subclassCode` and `protocolCode` are required
|
|
5
7
|
* for selecting correct USB configuration and interface.
|
|
6
8
|
*/
|
|
7
|
-
export type
|
|
8
|
-
export declare function
|
|
9
|
+
export type UsbInterfaceFilter = PickNonNullable<USBDeviceFilter, "classCode" | "subclassCode" | "protocolCode">;
|
|
10
|
+
export declare function isUsbInterfaceFilter(filter: USBDeviceFilter): filter is UsbInterfaceFilter;
|
|
11
|
+
export interface UsbInterfaceIdentifier {
|
|
9
12
|
configuration: USBConfiguration;
|
|
10
13
|
interface_: USBInterface;
|
|
11
14
|
alternate: USBAlternateInterface;
|
|
12
|
-
}
|
|
15
|
+
}
|
|
16
|
+
export declare function findUsbInterface(device: USBDevice, filter: UsbInterfaceFilter): UsbInterfaceIdentifier | undefined;
|
|
13
17
|
export declare function getSerialNumber(device: USBDevice): string;
|
|
18
|
+
/**
|
|
19
|
+
* Find the first pair of input and output endpoints from an alternate interface.
|
|
20
|
+
*
|
|
21
|
+
* ADB interface only has two endpoints, one for input and one for output.
|
|
22
|
+
*/
|
|
23
|
+
export declare function findUsbEndpoints(endpoints: USBEndpoint[]): {
|
|
24
|
+
inEndpoint: USBEndpoint;
|
|
25
|
+
outEndpoint: USBEndpoint;
|
|
26
|
+
};
|
|
27
|
+
export declare function matchFilter(device: USBDevice, filter: USBDeviceFilter & UsbInterfaceFilter): UsbInterfaceIdentifier | false;
|
|
28
|
+
export declare function matchFilter(device: USBDevice, filter: USBDeviceFilter): boolean;
|
|
29
|
+
export declare function matchFilters(device: USBDevice, filters: (USBDeviceFilter & UsbInterfaceFilter)[], exclusionFilters?: USBDeviceFilter[]): UsbInterfaceIdentifier | false;
|
|
30
|
+
export declare function matchFilters(device: USBDevice, filters: USBDeviceFilter[], exclusionFilters?: USBDeviceFilter[]): boolean;
|
|
14
31
|
//# sourceMappingURL=utils.d.ts.map
|
package/esm/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,IAAI,KAAK,CAOhE;AAED,MAAM,MAAM,eAAe,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI;KAC/C,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAChC,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG,eAAe,CAC5C,eAAe,EACf,WAAW,GAAG,cAAc,GAAG,cAAc,CAChD,CAAC;AAEF,wBAAgB,oBAAoB,CAChC,MAAM,EAAE,eAAe,GACxB,MAAM,IAAI,kBAAkB,CAM9B;AAaD,MAAM,WAAW,sBAAsB;IACnC,aAAa,EAAE,gBAAgB,CAAC;IAChC,UAAU,EAAE,YAAY,CAAC;IACzB,SAAS,EAAE,qBAAqB,CAAC;CACpC;AAED,wBAAgB,gBAAgB,CAC5B,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,kBAAkB,GAC3B,sBAAsB,GAAG,SAAS,CAWpC;AAMD,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,UAMhD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,WAAW,EAAE;;;EAgCxD;AAED,wBAAgB,WAAW,CACvB,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,eAAe,GAAG,kBAAkB,GAC7C,sBAAsB,GAAG,KAAK,CAAC;AAClC,wBAAgB,WAAW,CACvB,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,eAAe,GACxB,OAAO,CAAC;AA8BX,wBAAgB,YAAY,CACxB,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,CAAC,eAAe,GAAG,kBAAkB,CAAC,EAAE,EACjD,gBAAgB,CAAC,EAAE,eAAe,EAAE,GACrC,sBAAsB,GAAG,KAAK,CAAC;AAClC,wBAAgB,YAAY,CACxB,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,eAAe,EAAE,EAC1B,gBAAgB,CAAC,EAAE,eAAe,EAAE,GACrC,OAAO,CAAC"}
|
package/esm/utils.js
CHANGED
|
@@ -4,22 +4,27 @@ export function isErrorName(e, name) {
|
|
|
4
4
|
// https://github.com/node-usb/node-usb/issues/573
|
|
5
5
|
return (typeof e === "object" && e !== null && "name" in e && e.name === name);
|
|
6
6
|
}
|
|
7
|
-
function
|
|
8
|
-
return
|
|
7
|
+
export function isUsbInterfaceFilter(filter) {
|
|
8
|
+
return (filter.classCode !== undefined &&
|
|
9
|
+
filter.subclassCode !== undefined &&
|
|
10
|
+
filter.protocolCode !== undefined);
|
|
11
|
+
}
|
|
12
|
+
function matchUsbInterfaceFilter(alternate, filter) {
|
|
13
|
+
return (alternate.interfaceClass === filter.classCode &&
|
|
9
14
|
alternate.interfaceSubclass === filter.subclassCode &&
|
|
10
15
|
alternate.interfaceProtocol === filter.protocolCode);
|
|
11
16
|
}
|
|
12
|
-
export function
|
|
17
|
+
export function findUsbInterface(device, filter) {
|
|
13
18
|
for (const configuration of device.configurations) {
|
|
14
19
|
for (const interface_ of configuration.interfaces) {
|
|
15
20
|
for (const alternate of interface_.alternates) {
|
|
16
|
-
if (
|
|
21
|
+
if (matchUsbInterfaceFilter(alternate, filter)) {
|
|
17
22
|
return { configuration, interface_, alternate };
|
|
18
23
|
}
|
|
19
24
|
}
|
|
20
25
|
}
|
|
21
26
|
}
|
|
22
|
-
|
|
27
|
+
return undefined;
|
|
23
28
|
}
|
|
24
29
|
function padNumber(value) {
|
|
25
30
|
return value.toString(16).padStart(4, "0");
|
|
@@ -30,4 +35,70 @@ export function getSerialNumber(device) {
|
|
|
30
35
|
}
|
|
31
36
|
return padNumber(device.vendorId) + "x" + padNumber(device.productId);
|
|
32
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Find the first pair of input and output endpoints from an alternate interface.
|
|
40
|
+
*
|
|
41
|
+
* ADB interface only has two endpoints, one for input and one for output.
|
|
42
|
+
*/
|
|
43
|
+
export function findUsbEndpoints(endpoints) {
|
|
44
|
+
if (endpoints.length === 0) {
|
|
45
|
+
throw new TypeError("No endpoints given");
|
|
46
|
+
}
|
|
47
|
+
let inEndpoint;
|
|
48
|
+
let outEndpoint;
|
|
49
|
+
for (const endpoint of endpoints) {
|
|
50
|
+
switch (endpoint.direction) {
|
|
51
|
+
case "in":
|
|
52
|
+
inEndpoint = endpoint;
|
|
53
|
+
if (outEndpoint) {
|
|
54
|
+
return { inEndpoint, outEndpoint };
|
|
55
|
+
}
|
|
56
|
+
break;
|
|
57
|
+
case "out":
|
|
58
|
+
outEndpoint = endpoint;
|
|
59
|
+
if (inEndpoint) {
|
|
60
|
+
return { inEndpoint, outEndpoint };
|
|
61
|
+
}
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (!inEndpoint) {
|
|
66
|
+
throw new TypeError("No input endpoint found.");
|
|
67
|
+
}
|
|
68
|
+
if (!outEndpoint) {
|
|
69
|
+
throw new TypeError("No output endpoint found.");
|
|
70
|
+
}
|
|
71
|
+
throw new Error("unreachable");
|
|
72
|
+
}
|
|
73
|
+
export function matchFilter(device, filter) {
|
|
74
|
+
if (filter.vendorId !== undefined && device.vendorId !== filter.vendorId) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
if (filter.productId !== undefined &&
|
|
78
|
+
device.productId !== filter.productId) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
if (filter.serialNumber !== undefined &&
|
|
82
|
+
getSerialNumber(device) !== filter.serialNumber) {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
if (isUsbInterfaceFilter(filter)) {
|
|
86
|
+
return findUsbInterface(device, filter) || false;
|
|
87
|
+
}
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
export function matchFilters(device, filters, exclusionFilters) {
|
|
91
|
+
if (exclusionFilters && exclusionFilters.length > 0) {
|
|
92
|
+
if (matchFilters(device, exclusionFilters)) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
for (const filter of filters) {
|
|
97
|
+
const result = matchFilter(device, filter);
|
|
98
|
+
if (result) {
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
33
104
|
//# sourceMappingURL=utils.js.map
|
package/esm/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,WAAW,CAAC,CAAU,EAAE,IAAY;IAChD,+CAA+C;IAC/C,wBAAwB;IACxB,kDAAkD;IAClD,OAAO,CACH,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAI,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,CACxE,CAAC;AACN,CAAC;
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yume-chan/adb-daemon-webusb",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Adb daemon transport connection for `@yume-chan/adb` using WebUSB API.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"webusb",
|
|
@@ -24,21 +24,25 @@
|
|
|
24
24
|
"type": "module",
|
|
25
25
|
"main": "esm/index.js",
|
|
26
26
|
"types": "esm/index.d.ts",
|
|
27
|
+
"sideEffects": false,
|
|
27
28
|
"dependencies": {
|
|
28
29
|
"@types/w3c-web-usb": "^1.0.10",
|
|
29
|
-
"@yume-chan/adb": "^0.0
|
|
30
|
-
"@yume-chan/stream-extra": "^0.0
|
|
31
|
-
"@yume-chan/struct": "^0.0
|
|
30
|
+
"@yume-chan/adb": "^1.0.0",
|
|
31
|
+
"@yume-chan/stream-extra": "^1.0.0",
|
|
32
|
+
"@yume-chan/struct": "^1.0.0",
|
|
33
|
+
"@yume-chan/event": "^1.0.0"
|
|
32
34
|
},
|
|
33
35
|
"devDependencies": {
|
|
36
|
+
"@types/node": "^22.10.0",
|
|
37
|
+
"prettier": "^3.4.1",
|
|
38
|
+
"typescript": "^5.7.2",
|
|
39
|
+
"@yume-chan/test-runner": "^1.0.0",
|
|
34
40
|
"@yume-chan/eslint-config": "^1.0.0",
|
|
35
|
-
"@yume-chan/tsconfig": "^1.0.0"
|
|
36
|
-
"prettier": "^3.3.2",
|
|
37
|
-
"typescript": "^5.4.5"
|
|
41
|
+
"@yume-chan/tsconfig": "^1.0.0"
|
|
38
42
|
},
|
|
39
43
|
"scripts": {
|
|
40
44
|
"build": "tsc -b tsconfig.build.json",
|
|
41
|
-
"
|
|
42
|
-
"
|
|
45
|
+
"lint": "run-eslint && prettier src/**/*.ts --write --tab-width 4",
|
|
46
|
+
"test": "run-test"
|
|
43
47
|
}
|
|
44
48
|
}
|
package/src/device.ts
CHANGED
|
@@ -20,61 +20,35 @@ import {
|
|
|
20
20
|
pipeFrom,
|
|
21
21
|
} from "@yume-chan/stream-extra";
|
|
22
22
|
import type { ExactReadable } from "@yume-chan/struct";
|
|
23
|
-
import {
|
|
23
|
+
import { EmptyUint8Array } from "@yume-chan/struct";
|
|
24
24
|
|
|
25
|
-
import type {
|
|
26
|
-
import {
|
|
27
|
-
findUsbAlternateInterface,
|
|
28
|
-
getSerialNumber,
|
|
29
|
-
isErrorName,
|
|
30
|
-
} from "./utils.js";
|
|
25
|
+
import type { UsbInterfaceFilter, UsbInterfaceIdentifier } from "./utils.js";
|
|
26
|
+
import { findUsbEndpoints, getSerialNumber, isErrorName } from "./utils.js";
|
|
31
27
|
|
|
32
28
|
/**
|
|
33
29
|
* The default filter for ADB devices, as defined by Google.
|
|
34
30
|
*/
|
|
35
|
-
export const
|
|
31
|
+
export const AdbDefaultInterfaceFilter = {
|
|
36
32
|
classCode: 0xff,
|
|
37
33
|
subclassCode: 0x42,
|
|
38
34
|
protocolCode: 1,
|
|
39
|
-
} as const satisfies
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
switch (endpoint.direction) {
|
|
56
|
-
case "in":
|
|
57
|
-
inEndpoint = endpoint;
|
|
58
|
-
if (outEndpoint) {
|
|
59
|
-
return { inEndpoint, outEndpoint };
|
|
60
|
-
}
|
|
61
|
-
break;
|
|
62
|
-
case "out":
|
|
63
|
-
outEndpoint = endpoint;
|
|
64
|
-
if (inEndpoint) {
|
|
65
|
-
return { inEndpoint, outEndpoint };
|
|
66
|
-
}
|
|
67
|
-
break;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
if (!inEndpoint) {
|
|
72
|
-
throw new TypeError("No input endpoint found.");
|
|
73
|
-
}
|
|
74
|
-
if (!outEndpoint) {
|
|
75
|
-
throw new TypeError("No output endpoint found.");
|
|
35
|
+
} as const satisfies UsbInterfaceFilter;
|
|
36
|
+
|
|
37
|
+
export function mergeDefaultAdbInterfaceFilter(
|
|
38
|
+
filters: USBDeviceFilter[] | undefined,
|
|
39
|
+
): (USBDeviceFilter & UsbInterfaceFilter)[] {
|
|
40
|
+
if (!filters || filters.length === 0) {
|
|
41
|
+
return [AdbDefaultInterfaceFilter];
|
|
42
|
+
} else {
|
|
43
|
+
return filters.map((filter) => ({
|
|
44
|
+
...filter,
|
|
45
|
+
classCode: filter.classCode ?? AdbDefaultInterfaceFilter.classCode,
|
|
46
|
+
subclassCode:
|
|
47
|
+
filter.subclassCode ?? AdbDefaultInterfaceFilter.subclassCode,
|
|
48
|
+
protocolCode:
|
|
49
|
+
filter.protocolCode ?? AdbDefaultInterfaceFilter.protocolCode,
|
|
50
|
+
}));
|
|
76
51
|
}
|
|
77
|
-
throw new Error("unreachable");
|
|
78
52
|
}
|
|
79
53
|
|
|
80
54
|
class Uint8ArrayExactReadable implements ExactReadable {
|
|
@@ -203,7 +177,7 @@ export class AdbDaemonWebUsbConnection
|
|
|
203
177
|
if (zeroMask && (chunk.length & zeroMask) === 0) {
|
|
204
178
|
await device.raw.transferOut(
|
|
205
179
|
outEndpoint.endpointNumber,
|
|
206
|
-
|
|
180
|
+
EmptyUint8Array,
|
|
207
181
|
);
|
|
208
182
|
}
|
|
209
183
|
} catch (e) {
|
|
@@ -252,7 +226,7 @@ export class AdbDaemonWebUsbConnection
|
|
|
252
226
|
);
|
|
253
227
|
packet.payload = new Uint8Array(result.data!.buffer);
|
|
254
228
|
} else {
|
|
255
|
-
packet.payload =
|
|
229
|
+
packet.payload = EmptyUint8Array;
|
|
256
230
|
}
|
|
257
231
|
|
|
258
232
|
return packet;
|
|
@@ -260,7 +234,7 @@ export class AdbDaemonWebUsbConnection
|
|
|
260
234
|
} catch (e) {
|
|
261
235
|
// On Windows, disconnecting the device will cause `NetworkError` to be thrown,
|
|
262
236
|
// even before the `disconnect` event is fired.
|
|
263
|
-
//
|
|
237
|
+
// Wait a little while and check if the device is still connected.
|
|
264
238
|
// https://github.com/WICG/webusb/issues/219
|
|
265
239
|
if (isErrorName(e, "NetworkError")) {
|
|
266
240
|
await new Promise<void>((resolve) => {
|
|
@@ -271,8 +245,6 @@ export class AdbDaemonWebUsbConnection
|
|
|
271
245
|
|
|
272
246
|
if (closed) {
|
|
273
247
|
return undefined;
|
|
274
|
-
} else {
|
|
275
|
-
throw e;
|
|
276
248
|
}
|
|
277
249
|
}
|
|
278
250
|
|
|
@@ -282,7 +254,7 @@ export class AdbDaemonWebUsbConnection
|
|
|
282
254
|
}
|
|
283
255
|
|
|
284
256
|
export class AdbDaemonWebUsbDevice implements AdbDaemonDevice {
|
|
285
|
-
#
|
|
257
|
+
#interface: UsbInterfaceIdentifier;
|
|
286
258
|
#usbManager: USB;
|
|
287
259
|
|
|
288
260
|
#raw: USBDevice;
|
|
@@ -307,22 +279,24 @@ export class AdbDaemonWebUsbDevice implements AdbDaemonDevice {
|
|
|
307
279
|
*/
|
|
308
280
|
constructor(
|
|
309
281
|
device: USBDevice,
|
|
310
|
-
|
|
282
|
+
interface_: UsbInterfaceIdentifier,
|
|
311
283
|
usbManager: USB,
|
|
312
284
|
) {
|
|
313
285
|
this.#raw = device;
|
|
314
286
|
this.#serial = getSerialNumber(device);
|
|
315
|
-
this.#
|
|
287
|
+
this.#interface = interface_;
|
|
316
288
|
this.#usbManager = usbManager;
|
|
317
289
|
}
|
|
318
290
|
|
|
319
|
-
async #claimInterface(): Promise<
|
|
291
|
+
async #claimInterface(): Promise<{
|
|
292
|
+
inEndpoint: USBEndpoint;
|
|
293
|
+
outEndpoint: USBEndpoint;
|
|
294
|
+
}> {
|
|
320
295
|
if (!this.#raw.opened) {
|
|
321
296
|
await this.#raw.open();
|
|
322
297
|
}
|
|
323
298
|
|
|
324
|
-
const { configuration, interface_, alternate } =
|
|
325
|
-
findUsbAlternateInterface(this.#raw, this.#filters);
|
|
299
|
+
const { configuration, interface_, alternate } = this.#interface;
|
|
326
300
|
|
|
327
301
|
if (
|
|
328
302
|
this.#raw.configuration?.configurationValue !==
|
|
@@ -336,7 +310,15 @@ export class AdbDaemonWebUsbDevice implements AdbDaemonDevice {
|
|
|
336
310
|
}
|
|
337
311
|
|
|
338
312
|
if (!interface_.claimed) {
|
|
339
|
-
|
|
313
|
+
try {
|
|
314
|
+
await this.#raw.claimInterface(interface_.interfaceNumber);
|
|
315
|
+
} catch (e) {
|
|
316
|
+
if (isErrorName(e, "NetworkError")) {
|
|
317
|
+
throw new AdbDaemonWebUsbDevice.DeviceBusyError(e);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
throw e;
|
|
321
|
+
}
|
|
340
322
|
}
|
|
341
323
|
|
|
342
324
|
if (
|
|
@@ -348,18 +330,14 @@ export class AdbDaemonWebUsbDevice implements AdbDaemonDevice {
|
|
|
348
330
|
);
|
|
349
331
|
}
|
|
350
332
|
|
|
351
|
-
|
|
352
|
-
alternate.endpoints,
|
|
353
|
-
);
|
|
354
|
-
return [inEndpoint, outEndpoint];
|
|
333
|
+
return findUsbEndpoints(alternate.endpoints);
|
|
355
334
|
}
|
|
356
335
|
|
|
357
336
|
/**
|
|
358
|
-
*
|
|
359
|
-
* @returns The pair of `AdbPacket` streams.
|
|
337
|
+
* Open the device and create a new connection to the ADB Daemon.
|
|
360
338
|
*/
|
|
361
339
|
async connect(): Promise<AdbDaemonWebUsbConnection> {
|
|
362
|
-
const
|
|
340
|
+
const { inEndpoint, outEndpoint } = await this.#claimInterface();
|
|
363
341
|
return new AdbDaemonWebUsbConnection(
|
|
364
342
|
this,
|
|
365
343
|
inEndpoint,
|
|
@@ -368,3 +346,13 @@ export class AdbDaemonWebUsbDevice implements AdbDaemonDevice {
|
|
|
368
346
|
);
|
|
369
347
|
}
|
|
370
348
|
}
|
|
349
|
+
|
|
350
|
+
export namespace AdbDaemonWebUsbDevice {
|
|
351
|
+
export class DeviceBusyError extends Error {
|
|
352
|
+
constructor(cause?: Error) {
|
|
353
|
+
super("The device is already in used by another program", {
|
|
354
|
+
cause,
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
package/src/index.ts
CHANGED
package/src/manager.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import { ADB_DEFAULT_DEVICE_FILTER, AdbDaemonWebUsbDevice } from "./device.js";
|
|
2
|
-
import type { AdbDeviceFilter } from "./utils.js";
|
|
3
1
|
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
} from "./
|
|
2
|
+
AdbDaemonWebUsbDevice,
|
|
3
|
+
mergeDefaultAdbInterfaceFilter,
|
|
4
|
+
} from "./device.js";
|
|
5
|
+
import { AdbDaemonWebUsbDeviceObserver } from "./observer.js";
|
|
6
|
+
import { isErrorName, matchFilters } from "./utils.js";
|
|
8
7
|
|
|
9
8
|
export namespace AdbDaemonWebUsbDeviceManager {
|
|
10
9
|
export interface RequestDeviceOptions {
|
|
11
|
-
filters?:
|
|
10
|
+
filters?: USBDeviceFilter[] | undefined;
|
|
12
11
|
exclusionFilters?: USBDeviceFilter[] | undefined;
|
|
13
12
|
}
|
|
14
13
|
}
|
|
@@ -36,34 +35,33 @@ export class AdbDaemonWebUsbDeviceManager {
|
|
|
36
35
|
}
|
|
37
36
|
|
|
38
37
|
/**
|
|
39
|
-
*
|
|
40
|
-
* This is a convince method for `usb.requestDevice()`.
|
|
41
|
-
* @param filters
|
|
42
|
-
* The filters to apply to the device list.
|
|
43
|
-
*
|
|
44
|
-
* It must have `classCode`, `subclassCode` and `protocolCode` fields for selecting the ADB interface,
|
|
45
|
-
* but might also have `vendorId`, `productId` or `serialNumber` fields to limit the displayed device list.
|
|
46
|
-
*
|
|
47
|
-
* Defaults to {@link ADB_DEFAULT_DEVICE_FILTER}.
|
|
48
|
-
* @returns An {@link AdbDaemonWebUsbDevice} instance if the user selected a device,
|
|
49
|
-
* or `undefined` if the user cancelled the device picker.
|
|
38
|
+
* Call `USB#requestDevice()` to prompt the user to select a device.
|
|
50
39
|
*/
|
|
51
40
|
async requestDevice(
|
|
52
41
|
options: AdbDaemonWebUsbDeviceManager.RequestDeviceOptions = {},
|
|
53
42
|
): Promise<AdbDaemonWebUsbDevice | undefined> {
|
|
54
|
-
|
|
55
|
-
options.filters = [ADB_DEFAULT_DEVICE_FILTER];
|
|
56
|
-
} else if (options.filters.length === 0) {
|
|
57
|
-
throw new TypeError("filters must not be empty");
|
|
58
|
-
}
|
|
43
|
+
const filters = mergeDefaultAdbInterfaceFilter(options.filters);
|
|
59
44
|
|
|
60
45
|
try {
|
|
61
|
-
const device = await this.#usbManager.requestDevice(
|
|
62
|
-
|
|
46
|
+
const device = await this.#usbManager.requestDevice({
|
|
47
|
+
filters,
|
|
48
|
+
exclusionFilters: options.exclusionFilters,
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const interface_ = matchFilters(
|
|
52
|
+
device,
|
|
53
|
+
filters,
|
|
54
|
+
options.exclusionFilters,
|
|
63
55
|
);
|
|
56
|
+
if (!interface_) {
|
|
57
|
+
// `#usbManager` doesn't support `exclusionFilters`,
|
|
58
|
+
// selected device is invalid
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
|
|
64
62
|
return new AdbDaemonWebUsbDevice(
|
|
65
63
|
device,
|
|
66
|
-
|
|
64
|
+
interface_,
|
|
67
65
|
this.#usbManager,
|
|
68
66
|
);
|
|
69
67
|
} catch (e) {
|
|
@@ -77,63 +75,39 @@ export class AdbDaemonWebUsbDeviceManager {
|
|
|
77
75
|
}
|
|
78
76
|
|
|
79
77
|
/**
|
|
80
|
-
* Get all connected and
|
|
81
|
-
* This is a convince method for `usb.getDevices()`.
|
|
82
|
-
* @param filters
|
|
83
|
-
* The filters to apply to the device list.
|
|
84
|
-
*
|
|
85
|
-
* It must have `classCode`, `subclassCode` and `protocolCode` fields for selecting the ADB interface,
|
|
86
|
-
* but might also have `vendorId`, `productId` or `serialNumber` fields to limit the device list.
|
|
87
|
-
*
|
|
88
|
-
* Defaults to {@link ADB_DEFAULT_DEVICE_FILTER}.
|
|
89
|
-
* @returns An array of {@link AdbDaemonWebUsbDevice} instances for all connected and authenticated devices.
|
|
78
|
+
* Get all connected and requested devices that match the specified filters.
|
|
90
79
|
*/
|
|
91
80
|
async getDevices(
|
|
92
|
-
|
|
81
|
+
options: AdbDaemonWebUsbDeviceManager.RequestDeviceOptions = {},
|
|
93
82
|
): Promise<AdbDaemonWebUsbDevice[]> {
|
|
94
|
-
|
|
95
|
-
throw new TypeError("filters must not be empty");
|
|
96
|
-
}
|
|
83
|
+
const filters = mergeDefaultAdbInterfaceFilter(options.filters);
|
|
97
84
|
|
|
98
85
|
const devices = await this.#usbManager.getDevices();
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
"productId" in filter &&
|
|
110
|
-
device.productId !== filter.productId
|
|
111
|
-
) {
|
|
112
|
-
continue;
|
|
113
|
-
}
|
|
114
|
-
if (
|
|
115
|
-
"serialNumber" in filter &&
|
|
116
|
-
getSerialNumber(device) !== filter.serialNumber
|
|
117
|
-
) {
|
|
118
|
-
continue;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
try {
|
|
122
|
-
findUsbAlternateInterface(device, filters);
|
|
123
|
-
return true;
|
|
124
|
-
} catch {
|
|
125
|
-
continue;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
return false;
|
|
129
|
-
})
|
|
130
|
-
.map(
|
|
131
|
-
(device) =>
|
|
86
|
+
// filter map
|
|
87
|
+
const result: AdbDaemonWebUsbDevice[] = [];
|
|
88
|
+
for (const device of devices) {
|
|
89
|
+
const interface_ = matchFilters(
|
|
90
|
+
device,
|
|
91
|
+
filters,
|
|
92
|
+
options.exclusionFilters,
|
|
93
|
+
);
|
|
94
|
+
if (interface_) {
|
|
95
|
+
result.push(
|
|
132
96
|
new AdbDaemonWebUsbDevice(
|
|
133
97
|
device,
|
|
134
|
-
|
|
98
|
+
interface_,
|
|
135
99
|
this.#usbManager,
|
|
136
100
|
),
|
|
137
|
-
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return result;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
trackDevices(
|
|
109
|
+
options: AdbDaemonWebUsbDeviceManager.RequestDeviceOptions = {},
|
|
110
|
+
): AdbDaemonWebUsbDeviceObserver {
|
|
111
|
+
return new AdbDaemonWebUsbDeviceObserver(this.#usbManager, options);
|
|
138
112
|
}
|
|
139
113
|
}
|