New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@yume-chan/adb-daemon-webusb

Package Overview
Dependencies
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@yume-chan/adb-daemon-webusb - npm Package Compare versions

Comparing version 0.0.21 to 0.0.22

18

CHANGELOG.json

@@ -5,2 +5,20 @@ {

{
"version": "0.0.22",
"tag": "@yume-chan/adb-daemon-webusb_v0.0.22",
"date": "Wed, 13 Dec 2023 05:57:27 GMT",
"comments": {
"none": [
{
"comment": "Check incoming packet size to prevent Chrome from crashing"
},
{
"comment": "Add `exclusionFilters` option to `AdbDaemonWebUsbDeviceManager#requestDevice` method"
},
{
"comment": "`AdbDaemonWebUsbDevice` will generate a fake serial number from vid and pid if the device serial number is empty"
}
]
}
},
{
"version": "0.0.21",

@@ -7,0 +25,0 @@ "tag": "@yume-chan/adb-daemon-webusb_v0.0.21",

11

CHANGELOG.md
# Change Log - @yume-chan/adb-daemon-webusb
This log was last generated on Fri, 25 Aug 2023 14:05:18 GMT and should not be manually modified.
This log was last generated on Wed, 13 Dec 2023 05:57:27 GMT and should not be manually modified.
## 0.0.22
Wed, 13 Dec 2023 05:57:27 GMT
### Updates
- Check incoming packet size to prevent Chrome from crashing
- Add `exclusionFilters` option to `AdbDaemonWebUsbDeviceManager#requestDevice` method
- `AdbDaemonWebUsbDevice` will generate a fake serial number from vid and pid if the device serial number is empty
## 0.0.21

@@ -6,0 +15,0 @@ Fri, 25 Aug 2023 14:05:18 GMT

7

esm/device.d.ts

@@ -16,2 +16,5 @@ /// <reference types="w3c-web-usb" />

#private;
get device(): AdbDaemonWebUsbDevice;
get inEndpoint(): USBEndpoint;
get outEndpoint(): USBEndpoint;
get readable(): ReadableStream<AdbPacketData>;

@@ -26,3 +29,3 @@ get writable(): WritableStream<Consumable<{

}>>;
constructor(device: USBDevice, inEndpoint: USBEndpoint, outEndpoint: USBEndpoint, usbManager: USB);
constructor(device: AdbDaemonWebUsbDevice, inEndpoint: USBEndpoint, outEndpoint: USBEndpoint, usbManager: USB);
}

@@ -45,4 +48,4 @@ export declare class AdbDaemonWebUsbDevice implements AdbDaemonDevice {

*/
connect(): Promise<ReadableWritablePair<AdbPacketData, Consumable<AdbPacketInit>>>;
connect(): Promise<AdbDaemonWebUsbConnection>;
}
//# sourceMappingURL=device.d.ts.map

@@ -65,2 +65,14 @@ import { AdbPacketHeader, AdbPacketSerializeStream, unreachable, } from "@yume-chan/adb";

export class AdbDaemonWebUsbConnection {
#device;
get device() {
return this.#device;
}
#inEndpoint;
get inEndpoint() {
return this.#inEndpoint;
}
#outEndpoint;
get outEndpoint() {
return this.#outEndpoint;
}
#readable;

@@ -75,2 +87,5 @@ get readable() {

constructor(device, inEndpoint, outEndpoint, usbManager) {
this.#device = device;
this.#inEndpoint = inEndpoint;
this.#outEndpoint = outEndpoint;
let closed = false;

@@ -81,3 +96,3 @@ const duplex = new DuplexStreamFactory({

closed = true;
await device.close();
await device.raw.close();
}

@@ -94,3 +109,3 @@ catch {

function handleUsbDisconnect(e) {
if (e.device === device) {
if (e.device === device.raw) {
duplex.dispose().catch(unreachable);

@@ -101,45 +116,12 @@ }

this.#readable = duplex.wrapReadable(new ReadableStream({
async pull(controller) {
try {
// The `length` argument in `transferIn` must not be smaller than what the device sent,
// otherwise it will return `babble` status without any data.
// ADB daemon sends each packet in two parts, the 24-byte header and the payload.
const result = await device.transferIn(inEndpoint.endpointNumber, 24);
// TODO: webusb: handle `babble` by discarding the data and receive again
// Per spec, the `result.data` always covers the whole `buffer`.
const buffer = new Uint8Array(result.data.buffer);
const stream = new Uint8ArrayExactReadable(buffer);
// Add `payload` field to its type, it's assigned below.
const packet = AdbPacketHeader.deserialize(stream);
if (packet.payloadLength !== 0) {
const result = await device.transferIn(inEndpoint.endpointNumber, packet.payloadLength);
packet.payload = new Uint8Array(result.data.buffer);
}
else {
packet.payload = EMPTY_UINT8_ARRAY;
}
pull: async (controller) => {
const packet = await this.#transferIn();
if (packet) {
controller.enqueue(packet);
}
catch (e) {
// On Windows, disconnecting the device will cause `NetworkError` to be thrown,
// even before the `disconnect` event is fired.
// We need to wait a little bit and check if the device is still connected.
// https://github.com/WICG/webusb/issues/219
if (isErrorName(e, "NetworkError")) {
await new Promise((resolve) => {
setTimeout(() => {
resolve();
}, 100);
});
if (closed) {
controller.close();
}
else {
throw e;
}
}
throw e;
else {
controller.close();
}
},
}));
}, { highWaterMark: 0 }));
const zeroMask = outEndpoint.packetSize - 1;

@@ -149,3 +131,3 @@ this.#writable = pipeFrom(duplex.createWritable(new ConsumableWritableStream({

try {
await device.transferOut(outEndpoint.endpointNumber, chunk);
await device.raw.transferOut(outEndpoint.endpointNumber, chunk);
// In USB protocol, a not-full packet indicates the end of a transfer.

@@ -157,3 +139,3 @@ // If the payload size is a multiple of the packet size,

(chunk.byteLength & zeroMask) === 0) {
await device.transferOut(outEndpoint.endpointNumber, EMPTY_UINT8_ARRAY);
await device.raw.transferOut(outEndpoint.endpointNumber, EMPTY_UINT8_ARRAY);
}

@@ -170,2 +152,49 @@ }

}
async #transferIn() {
try {
while (true) {
// ADB daemon sends each packet in two parts, the 24-byte header and the payload.
const result = await this.#device.raw.transferIn(this.#inEndpoint.endpointNumber, this.#inEndpoint.packetSize);
if (result.data.byteLength !== 24) {
continue;
}
// Per spec, the `result.data` always covers the whole `buffer`.
const buffer = new Uint8Array(result.data.buffer);
const stream = new Uint8ArrayExactReadable(buffer);
// Add `payload` field to its type, it's assigned below.
const packet = AdbPacketHeader.deserialize(stream);
if (packet.magic !== (packet.command ^ 0xffffffff)) {
continue;
}
if (packet.payloadLength !== 0) {
const result = await this.#device.raw.transferIn(this.#inEndpoint.endpointNumber, packet.payloadLength);
packet.payload = new Uint8Array(result.data.buffer);
}
else {
packet.payload = EMPTY_UINT8_ARRAY;
}
return packet;
}
}
catch (e) {
// On Windows, disconnecting the device will cause `NetworkError` to be thrown,
// even before the `disconnect` event is fired.
// We need to wait a little bit and check if the device is still connected.
// https://github.com/WICG/webusb/issues/219
if (isErrorName(e, "NetworkError")) {
await new Promise((resolve) => {
setTimeout(() => {
resolve();
}, 100);
});
if (closed) {
return undefined;
}
else {
throw e;
}
}
throw e;
}
}
}

@@ -179,4 +208,5 @@ export class AdbDaemonWebUsbDevice {

}
#serial;
get serial() {
return this.#raw.serialNumber;
return this.#serial;
}

@@ -194,10 +224,15 @@ get name() {

this.#raw = device;
if (device.serialNumber) {
this.#serial = device.serialNumber;
}
else {
this.#serial =
device.vendorId.toString(16).padStart(4, "0") +
"x" +
device.productId.toString(16).padStart(4, "0");
}
this.#filters = filters;
this.#usbManager = usbManager;
}
/**
* Claim the device and create a pair of `AdbPacket` streams to the ADB interface.
* @returns The pair of `AdbPacket` streams.
*/
async connect() {
async #claimInterface() {
if (!this.#raw.opened) {

@@ -220,5 +255,13 @@ await this.#raw.open();

const { inEndpoint, outEndpoint } = findUsbEndpoints(alternate.endpoints);
return new AdbDaemonWebUsbConnection(this.#raw, inEndpoint, outEndpoint, this.#usbManager);
return [inEndpoint, outEndpoint];
}
/**
* Claim the device and create a pair of `AdbPacket` streams to the ADB interface.
* @returns The pair of `AdbPacket` streams.
*/
async connect() {
const [inEndpoint, outEndpoint] = await this.#claimInterface();
return new AdbDaemonWebUsbConnection(this, inEndpoint, outEndpoint, this.#usbManager);
}
}
//# sourceMappingURL=device.js.map
/// <reference types="w3c-web-usb" />
import { AdbDaemonWebUsbDevice } from "./device.js";
import type { AdbDeviceFilter } from "./utils.js";
export declare namespace AdbDaemonWebUsbDeviceManager {
interface RequestDeviceOptions {
filters?: AdbDeviceFilter[] | undefined;
exclusionFilters?: USBDeviceFilter[] | undefined;
}
}
export declare class AdbDaemonWebUsbDeviceManager {

@@ -30,3 +36,3 @@ #private;

*/
requestDevice(filters?: AdbDeviceFilter[]): Promise<AdbDaemonWebUsbDevice | undefined>;
requestDevice(options?: AdbDaemonWebUsbDeviceManager.RequestDeviceOptions): Promise<AdbDaemonWebUsbDevice | undefined>;
/**

@@ -33,0 +39,0 @@ * Get all connected and authenticated devices.

@@ -34,11 +34,12 @@ import { ADB_DEFAULT_DEVICE_FILTER, AdbDaemonWebUsbDevice } from "./device.js";

*/
async requestDevice(filters = [ADB_DEFAULT_DEVICE_FILTER]) {
if (filters.length === 0) {
async requestDevice(options = {}) {
if (!options.filters) {
options.filters = [ADB_DEFAULT_DEVICE_FILTER];
}
else if (options.filters.length === 0) {
throw new TypeError("filters must not be empty");
}
try {
const device = await this.#usbManager.requestDevice({
filters,
});
return new AdbDaemonWebUsbDevice(device, filters, this.#usbManager);
const device = await this.#usbManager.requestDevice(options);
return new AdbDaemonWebUsbDevice(device, options.filters, this.#usbManager);
}

@@ -45,0 +46,0 @@ catch (e) {

{
"name": "@yume-chan/adb-daemon-webusb",
"version": "0.0.21",
"version": "0.0.22",
"description": "Adb daemon transport connection for `@yume-chan/adb` using WebUSB API.",

@@ -28,7 +28,7 @@ "keywords": [

"dependencies": {
"@types/w3c-web-usb": "^1.0.6",
"@yume-chan/adb": "^0.0.21",
"@yume-chan/stream-extra": "^0.0.21",
"@yume-chan/struct": "^0.0.21",
"tslib": "^2.6.0"
"@types/w3c-web-usb": "^1.0.10",
"@yume-chan/adb": "^0.0.22",
"@yume-chan/stream-extra": "^0.0.22",
"@yume-chan/struct": "^0.0.22",
"tslib": "^2.6.2"
},

@@ -38,5 +38,5 @@ "devDependencies": {

"@yume-chan/tsconfig": "^1.0.0",
"eslint": "^8.44.0",
"prettier": "^3.0.0",
"typescript": "^5.1.6"
"eslint": "^8.55.0",
"prettier": "^3.1.0",
"typescript": "^5.3.2"
},

@@ -43,0 +43,0 @@ "scripts": {

@@ -1,130 +0,46 @@

# @yume-chan/adb-daemon-webusb
<p align="center">
<img alt="Tango" src="https://raw.githubusercontent.com/yume-chan/ya-webadb/main/.github/logo.svg" width="200">
</p>
ADB daemon transport device for `@yume-chan/adb` using WebUSB ([MDN](https://developer.mozilla.org/en-US/docs/Web/API/USB), [Spec](https://wicg.github.io/webusb)) API.
<h1 align="center">@yume-chan/adb-daemon-webusb</h1>
- [Use in browser](#use-in-browser)
- [Use in Node.js](#use-in-nodejs)
- [`AdbDaemonWebUsbDevice`](#adbdaemonwebusbdevice)
- [constructor](#constructor)
- [`raw`](#raw)
- [`connect`](#connect)
- [`AdbDaemonWebUsbDeviceManager`](#adbdaemonwebusbdevicemanager)
- [`BROWSER`](#browser)
- [constructor](#constructor-1)
- [`requestDevice`](#requestdevice)
- [`getDevices`](#getdevices)
- [Note on secure context](#note-on-secure-context)
<p align="center">
Adb daemon transport connection for `@yume-chan/adb` using WebUSB API.
</p>
## Use in browser
<p align="center">
<a href="https://github.com/yume-chan/ya-webadb/blob/main/LICENSE">
<img alt="MIT License" src="https://img.shields.io/github/license/yume-chan/ya-webadb">
</a>
<a href="https://github.com/yume-chan/ya-webadb/releases">
<img alt="GitHub release" src="https://img.shields.io/github/v/release/yume-chan/ya-webadb?logo=github">
</a>
<a href="https://www.npmjs.com/package/@yume-chan/adb">
<img alt="npm" src="https://img.shields.io/npm/dm/%40yume-chan/adb?logo=npm">
</a>
<a href="https://discord.gg/26k3ttC2PN">
<img alt="Discord" src="https://img.shields.io/discord/1120215514732564502?logo=discord&logoColor=%23ffffff&label=Discord">
</a>
</p>
| Chrome | Edge | Firefox | Internet Explorer | Safari |
| -------------- | -------------- | ------- | ----------------- | ------ |
| 61<sup>1</sup> | 79<sup>1</sup> | No | No | No |
This package is part of [Tango ADB](https://github.com/yume-chan/ya-webadb). Generally you need multiple packages to build a complete ADB client that can run on Web browsers and Node.js. Read the documentation for more information.
<sup>1</sup>: Chrome for Android is supported, Chrome for iOS is NOT supported.
## Documentation
## Use in Node.js
Check the latest documentation at https://tango-adb.github.io/docs/
| Node.js | `usb` NPM Package |
| ------- | ----------------- |
| 10.5 | 2.8.1 |
## Sponsors
Node.js doesn't have native support for WebUSB API, but the [`usb`](https://www.npmjs.com/package/usb) NPM package provides a WebUSB compatible API.
[Become a backer](https://opencollective.com/ya-webadb) and get your image on our README on Github with a link to your site.
To use a custom WebUSB API implementation, pass it to the constructor of `AdbDaemonWebUsbDevice`, `AdbDaemonWebUsbDeviceManager` and `AdbDaemonWebUsbConnectionWatcher` via the `usbManager` parameter.
## `AdbDaemonWebUsbDevice`
### constructor
```ts
public constructor(
device: USBDevice,
filters: AdbDeviceFilter[] = [ADB_DEFAULT_DEVICE_FILTER]
usbManager: USB
);
```
Create a new instance of `AdbDaemonWebUsbDevice` using a specified `USBDevice` instance.
`USBDevice` and `USB` types are from WebUSB API.
The `filters` parameter specifies the `classCode`, `subclassCode` and `protocolCode` to use when searching for ADB interface. The default value is `[{ classCode: 0xff, subclassCode: 0x42, protocolCode: 0x1 }]`, defined by Google.
### `raw`
```ts
public get raw(): USBDevice;
```
Gets the raw `USBDevice` from the device. Allow sending/receiving USB packets to other interfaces/endpoints. For example can be used with `@yume-chan/aoa` package.
### `connect`
```ts
public async connect(): Promise<
ReadableWritablePair<AdbPacketData, Consumable<AdbPacketInit>>
>
```
Claim the device and create a pair of `AdbPacket` streams to the ADB interface.
## `AdbDaemonWebUsbDeviceManager`
A helper class that wraps the WebUSB API.
### `BROWSER`
```ts
public static readonly BROWSER: AdbDaemonWebUsbDeviceManager | undefined;
```
Gets the instance of `AdbDaemonWebUsbDeviceManager` using browser WebUSB implementation.
May be `undefined` if the browser does not support WebUSB.
### constructor
```ts
public constructor(usbManager: USB);
```
Create a new instance of `AdbDaemonWebUsbDeviceManager` using the specified WebUSB API implementation.
### `requestDevice`
```ts
public async requestDevice(
filters: AdbDeviceFilter[] = [ADB_DEFAULT_DEVICE_FILTER]
): Promise<AdbDaemonWebUsbDevice | undefined>
```
Request access to a connected device.
This is a convince method for `usb.requestDevice()`.
The `filters` parameter must have `classCode`, `subclassCode` and `protocolCode` fields for selecting the ADB interface. It can also have `vendorId`, `productId` or `serialNumber` fields to limit the displayed device list.
Returns an `AdbDaemonWebUsbDevice` instance, or `undefined` if the user cancelled the picker.
### `getDevices`
```ts
public async getDevices(
filters: AdbDeviceFilter[] = [ADB_DEFAULT_DEVICE_FILTER]
): Promise<AdbDaemonWebUsbDevice[]>
```
Get all connected and authenticated devices.
This is a convince method for `usb.getDevices()`.
## Note on secure context
WebUSB requires a [secure context](https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts) (HTTPS).
`localhost` is considered secure, so local development works. But to access a self-hosted server running on another machine, either add a certificate, or add the domain name to the allowlist on each client machine:
1. Open `chrome://flags/#unsafely-treat-insecure-origin-as-secure`
2. Add the protocol and domain part of your url (e.g. `http://192.168.0.100:9000`) to the input box
3. Choose `Enable` from the dropdown menu
4. Restart browser
<a href="https://opencollective.com/ya-webadb/backer/0/website?requireActive=false" target="_blank"><img src="https://opencollective.com/ya-webadb/backer/0/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/ya-webadb/backer/1/website?requireActive=false" target="_blank"><img src="https://opencollective.com/ya-webadb/backer/1/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/ya-webadb/backer/2/website?requireActive=false" target="_blank"><img src="https://opencollective.com/ya-webadb/backer/2/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/ya-webadb/backer/3/website?requireActive=false" target="_blank"><img src="https://opencollective.com/ya-webadb/backer/3/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/ya-webadb/backer/4/website?requireActive=false" target="_blank"><img src="https://opencollective.com/ya-webadb/backer/4/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/ya-webadb/backer/5/website?requireActive=false" target="_blank"><img src="https://opencollective.com/ya-webadb/backer/5/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/ya-webadb/backer/6/website?requireActive=false" target="_blank"><img src="https://opencollective.com/ya-webadb/backer/6/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/ya-webadb/backer/7/website?requireActive=false" target="_blank"><img src="https://opencollective.com/ya-webadb/backer/7/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/ya-webadb/backer/8/website?requireActive=false" target="_blank"><img src="https://opencollective.com/ya-webadb/backer/8/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/ya-webadb/backer/9/website?requireActive=false" target="_blank"><img src="https://opencollective.com/ya-webadb/backer/9/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/ya-webadb/backer/10/website?requireActive=false" target="_blank"><img src="https://opencollective.com/ya-webadb/backer/10/avatar.svg?requireActive=false"></a>

@@ -102,2 +102,17 @@ import type {

{
#device: AdbDaemonWebUsbDevice;
get device() {
return this.#device;
}
#inEndpoint: USBEndpoint;
get inEndpoint() {
return this.#inEndpoint;
}
#outEndpoint: USBEndpoint;
get outEndpoint() {
return this.#outEndpoint;
}
#readable: ReadableStream<AdbPacketData>;

@@ -114,3 +129,3 @@ get readable() {

constructor(
device: USBDevice,
device: AdbDaemonWebUsbDevice,
inEndpoint: USBEndpoint,

@@ -120,2 +135,6 @@ outEndpoint: USBEndpoint,

) {
this.#device = device;
this.#inEndpoint = inEndpoint;
this.#outEndpoint = outEndpoint;
let closed = false;

@@ -130,3 +149,3 @@

closed = true;
await device.close();
await device.raw.close();
} catch {

@@ -146,3 +165,3 @@ /* device may have already disconnected */

function handleUsbDisconnect(e: USBConnectionEvent) {
if (e.device === device) {
if (e.device === device.raw) {
duplex.dispose().catch(unreachable);

@@ -155,59 +174,15 @@ }

this.#readable = duplex.wrapReadable(
new ReadableStream<AdbPacketData>({
async pull(controller) {
try {
// The `length` argument in `transferIn` must not be smaller than what the device sent,
// otherwise it will return `babble` status without any data.
// ADB daemon sends each packet in two parts, the 24-byte header and the payload.
const result = await device.transferIn(
inEndpoint.endpointNumber,
24,
);
// TODO: webusb: handle `babble` by discarding the data and receive again
// Per spec, the `result.data` always covers the whole `buffer`.
const buffer = new Uint8Array(result.data!.buffer);
const stream = new Uint8ArrayExactReadable(buffer);
// Add `payload` field to its type, it's assigned below.
const packet = AdbPacketHeader.deserialize(
stream,
) as AdbPacketHeader & { payload: Uint8Array };
if (packet.payloadLength !== 0) {
const result = await device.transferIn(
inEndpoint.endpointNumber,
packet.payloadLength,
);
packet.payload = new Uint8Array(
result.data!.buffer,
);
new ReadableStream<AdbPacketData>(
{
pull: async (controller) => {
const packet = await this.#transferIn();
if (packet) {
controller.enqueue(packet);
} else {
packet.payload = EMPTY_UINT8_ARRAY;
controller.close();
}
controller.enqueue(packet);
} catch (e) {
// On Windows, disconnecting the device will cause `NetworkError` to be thrown,
// even before the `disconnect` event is fired.
// We need to wait a little bit and check if the device is still connected.
// https://github.com/WICG/webusb/issues/219
if (isErrorName(e, "NetworkError")) {
await new Promise<void>((resolve) => {
setTimeout(() => {
resolve();
}, 100);
});
if (closed) {
controller.close();
} else {
throw e;
}
}
throw e;
}
},
},
}),
{ highWaterMark: 0 },
),
);

@@ -221,3 +196,3 @@

try {
await device.transferOut(
await device.raw.transferOut(
outEndpoint.endpointNumber,

@@ -235,3 +210,3 @@ chunk,

) {
await device.transferOut(
await device.raw.transferOut(
outEndpoint.endpointNumber,

@@ -253,2 +228,63 @@ EMPTY_UINT8_ARRAY,

}
async #transferIn(): Promise<AdbPacketData | undefined> {
try {
while (true) {
// ADB daemon sends each packet in two parts, the 24-byte header and the payload.
const result = await this.#device.raw.transferIn(
this.#inEndpoint.endpointNumber,
this.#inEndpoint.packetSize,
);
if (result.data!.byteLength !== 24) {
continue;
}
// Per spec, the `result.data` always covers the whole `buffer`.
const buffer = new Uint8Array(result.data!.buffer);
const stream = new Uint8ArrayExactReadable(buffer);
// Add `payload` field to its type, it's assigned below.
const packet = AdbPacketHeader.deserialize(
stream,
) as AdbPacketHeader & { payload: Uint8Array };
if (packet.magic !== (packet.command ^ 0xffffffff)) {
continue;
}
if (packet.payloadLength !== 0) {
const result = await this.#device.raw.transferIn(
this.#inEndpoint.endpointNumber,
packet.payloadLength,
);
packet.payload = new Uint8Array(result.data!.buffer);
} else {
packet.payload = EMPTY_UINT8_ARRAY;
}
return packet;
}
} catch (e) {
// On Windows, disconnecting the device will cause `NetworkError` to be thrown,
// even before the `disconnect` event is fired.
// We need to wait a little bit and check if the device is still connected.
// https://github.com/WICG/webusb/issues/219
if (isErrorName(e, "NetworkError")) {
await new Promise<void>((resolve) => {
setTimeout(() => {
resolve();
}, 100);
});
if (closed) {
return undefined;
} else {
throw e;
}
}
throw e;
}
}
}

@@ -265,4 +301,5 @@

#serial: string;
get serial(): string {
return this.#raw.serialNumber!;
return this.#serial;
}

@@ -286,2 +323,10 @@

this.#raw = device;
if (device.serialNumber) {
this.#serial = device.serialNumber;
} else {
this.#serial =
device.vendorId.toString(16).padStart(4, "0") +
"x" +
device.productId.toString(16).padStart(4, "0");
}
this.#filters = filters;

@@ -291,9 +336,3 @@ this.#usbManager = usbManager;

/**
* Claim the device and create a pair of `AdbPacket` streams to the ADB interface.
* @returns The pair of `AdbPacket` streams.
*/
async connect(): Promise<
ReadableWritablePair<AdbPacketData, Consumable<AdbPacketInit>>
> {
async #claimInterface(): Promise<[USBEndpoint, USBEndpoint]> {
if (!this.#raw.opened) {

@@ -333,4 +372,13 @@ await this.#raw.open();

);
return [inEndpoint, outEndpoint];
}
/**
* Claim the device and create a pair of `AdbPacket` streams to the ADB interface.
* @returns The pair of `AdbPacket` streams.
*/
async connect(): Promise<AdbDaemonWebUsbConnection> {
const [inEndpoint, outEndpoint] = await this.#claimInterface();
return new AdbDaemonWebUsbConnection(
this.#raw,
this,
inEndpoint,

@@ -337,0 +385,0 @@ outEndpoint,

@@ -5,2 +5,9 @@ import { ADB_DEFAULT_DEVICE_FILTER, AdbDaemonWebUsbDevice } from "./device.js";

export namespace AdbDaemonWebUsbDeviceManager {
export interface RequestDeviceOptions {
filters?: AdbDeviceFilter[] | undefined;
exclusionFilters?: USBDeviceFilter[] | undefined;
}
}
export class AdbDaemonWebUsbDeviceManager {

@@ -42,5 +49,7 @@ /**

async requestDevice(
filters: AdbDeviceFilter[] = [ADB_DEFAULT_DEVICE_FILTER],
options: AdbDaemonWebUsbDeviceManager.RequestDeviceOptions = {},
): Promise<AdbDaemonWebUsbDevice | undefined> {
if (filters.length === 0) {
if (!options.filters) {
options.filters = [ADB_DEFAULT_DEVICE_FILTER];
} else if (options.filters.length === 0) {
throw new TypeError("filters must not be empty");

@@ -50,6 +59,10 @@ }

try {
const device = await this.#usbManager.requestDevice({
filters,
});
return new AdbDaemonWebUsbDevice(device, filters, this.#usbManager);
const device = await this.#usbManager.requestDevice(
options as USBDeviceRequestOptions,
);
return new AdbDaemonWebUsbDevice(
device,
options.filters,
this.#usbManager,
);
} catch (e) {

@@ -56,0 +69,0 @@ // No device selected

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc