Loading apps/demo/components/connect.tsx +3 −11 Original line number Diff line number Diff line Loading @@ -158,25 +158,17 @@ function _Connect(): JSX.Element | null { try { setConnecting(true); const dataStreamPair = await selectedBackend.connect(); const packetStreamPair = Adb.createConnection({ readable: dataStreamPair.readable .pipeThrough(new InspectStream(chunk => { byteInAcc.current += chunk.byteLength; })), writable: dataStreamPair.writable, }); const streams = await selectedBackend.connect(); // Use `TransformStream` to intercept packets and log them const readable = packetStreamPair.readable const readable = streams.readable .pipeThrough( new InspectStream(packet => { globalState.appendLog('Incoming', packet); }) ); const writable = pipeFrom( packetStreamPair.writable, streams.writable, new InspectStream(packet => { globalState.appendLog('Outgoing', packet); }) Loading libraries/adb-backend-direct-sockets/src/index.ts +5 −4 Original line number Diff line number Diff line import { AdbBackend, ReadableStream, WrapReadableStream, WrapWritableStream, WritableStream } from '@yume-chan/adb'; import { AdbBackend, AdbPacket, AdbPacketSerializeStream, pipeFrom, ReadableStream, StructDeserializeStream, WrapReadableStream, WrapWritableStream, WritableStream } from '@yume-chan/adb'; declare global { interface TCPSocket { Loading Loading @@ -55,6 +55,7 @@ export default class AdbDirectSocketsBackend implements AdbBackend { remotePort: this.port, noDelay: true, }); // Native streams can't `pipeTo()` or `pipeThrough()` polyfilled streams, so we need to wrap them return { readable: new WrapReadableStream<Uint8Array, ReadableStream<Uint8Array>, void>({ Loading @@ -64,15 +65,15 @@ export default class AdbDirectSocketsBackend implements AdbBackend { state: undefined, }; } }), writable: new WrapWritableStream({ }).pipeThrough(new StructDeserializeStream(AdbPacket)), writable: pipeFrom(new WrapWritableStream({ async start() { return { writable, state: undefined, }; } }), }), new AdbPacketSerializeStream()), }; } } libraries/adb-backend-webusb/package.json +1 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ "dependencies": { "@types/w3c-web-usb": "^1.0.4", "@yume-chan/adb": "^0.0.10", "@yume-chan/struct": "^0.0.10", "tslib": "^2.3.1" }, "devDependencies": { Loading libraries/adb-backend-webusb/src/backend.ts +24 −16 Original line number Diff line number Diff line import { DuplexStreamFactory, type AdbBackend, type ReadableStream, type ReadableWritablePair, type WritableStream } from '@yume-chan/adb'; import { AdbPacket, AdbPacketSerializeStream, DuplexStreamFactory, pipeFrom, ReadableStream, type AdbBackend, type AdbPacketCore, type AdbPacketInit, type ReadableWritablePair, type WritableStream } from '@yume-chan/adb'; import type { StructAsyncDeserializeStream } from "@yume-chan/struct"; export const WebUsbDeviceFilter: USBDeviceFilter = { classCode: 0xFF, Loading @@ -6,15 +7,15 @@ export const WebUsbDeviceFilter: USBDeviceFilter = { protocolCode: 1, }; export class AdbWebUsbBackendStream implements ReadableWritablePair<Uint8Array, Uint8Array>{ private _readable: ReadableStream<Uint8Array>; export class AdbWebUsbBackendStream implements ReadableWritablePair<AdbPacketCore, AdbPacketInit>{ private _readable: ReadableStream<AdbPacketCore>; public get readable() { return this._readable; } private _writable: WritableStream<Uint8Array>; private _writable: WritableStream<AdbPacketInit>; public get writable() { return this._writable; } public constructor(device: USBDevice, inEndpoint: USBEndpoint, outEndpoint: USBEndpoint) { const factory = new DuplexStreamFactory<Uint8Array, Uint8Array>({ const factory = new DuplexStreamFactory<AdbPacketCore, Uint8Array>({ close: async () => { navigator.usb.removeEventListener('disconnect', handleUsbDisconnect); try { Loading @@ -33,9 +34,13 @@ export class AdbWebUsbBackendStream implements ReadableWritablePair<Uint8Array, navigator.usb.addEventListener('disconnect', handleUsbDisconnect); this._readable = factory.createReadable({ pull: async (controller) => { const result = await device.transferIn(inEndpoint.endpointNumber, inEndpoint.packetSize); const incomingStream: StructAsyncDeserializeStream = { async read(length) { // `ReadableStream<Uin8Array>` don't know how many bytes the consumer need in each `pull`, // But `transferIn(endpointNumber, packetSize)` is much slower than `transferIn(endpointNumber, length)` // So `AdbBackend` is refactored to use `ReadableStream<AdbPacketCore>` directly, // (let each backend deserialize the packets in their own way) const result = await device.transferIn(inEndpoint.endpointNumber, length); // `USBTransferResult` has three states: "ok", "stall" and "babble", // but ADBd on Android won't enter "stall" (halt) state, Loading @@ -44,22 +49,25 @@ export class AdbWebUsbBackendStream implements ReadableWritablePair<Uint8Array, // "babble" just means there is more data to be read. // From spec, the `result.data` always covers the whole `buffer`. const chunk = new Uint8Array(result.data!.buffer); controller.enqueue(chunk); return new Uint8Array(result.data!.buffer); } }; this._readable = factory.createWrapReadable(new ReadableStream<AdbPacketCore>({ async pull(controller) { const value = await AdbPacket.deserialize(incomingStream); controller.enqueue(value); }, }, { highWaterMark: 16 * 1024, size(chunk) { return chunk.byteLength; }, }); })); this._writable = factory.createWritable({ this._writable = pipeFrom(factory.createWritable({ write: async (chunk) => { await device.transferOut(outEndpoint.endpointNumber, chunk); }, }, { highWaterMark: 16 * 1024, size(chunk) { return chunk.byteLength; }, }); }), new AdbPacketSerializeStream()); } } Loading libraries/adb-backend-webusb/tsconfig.json +3 −0 Original line number Diff line number Diff line Loading @@ -12,6 +12,9 @@ "references": [ { "path": "../adb/tsconfig.build.json" }, { "path": "../struct/tsconfig.json" } ] } Loading
apps/demo/components/connect.tsx +3 −11 Original line number Diff line number Diff line Loading @@ -158,25 +158,17 @@ function _Connect(): JSX.Element | null { try { setConnecting(true); const dataStreamPair = await selectedBackend.connect(); const packetStreamPair = Adb.createConnection({ readable: dataStreamPair.readable .pipeThrough(new InspectStream(chunk => { byteInAcc.current += chunk.byteLength; })), writable: dataStreamPair.writable, }); const streams = await selectedBackend.connect(); // Use `TransformStream` to intercept packets and log them const readable = packetStreamPair.readable const readable = streams.readable .pipeThrough( new InspectStream(packet => { globalState.appendLog('Incoming', packet); }) ); const writable = pipeFrom( packetStreamPair.writable, streams.writable, new InspectStream(packet => { globalState.appendLog('Outgoing', packet); }) Loading
libraries/adb-backend-direct-sockets/src/index.ts +5 −4 Original line number Diff line number Diff line import { AdbBackend, ReadableStream, WrapReadableStream, WrapWritableStream, WritableStream } from '@yume-chan/adb'; import { AdbBackend, AdbPacket, AdbPacketSerializeStream, pipeFrom, ReadableStream, StructDeserializeStream, WrapReadableStream, WrapWritableStream, WritableStream } from '@yume-chan/adb'; declare global { interface TCPSocket { Loading Loading @@ -55,6 +55,7 @@ export default class AdbDirectSocketsBackend implements AdbBackend { remotePort: this.port, noDelay: true, }); // Native streams can't `pipeTo()` or `pipeThrough()` polyfilled streams, so we need to wrap them return { readable: new WrapReadableStream<Uint8Array, ReadableStream<Uint8Array>, void>({ Loading @@ -64,15 +65,15 @@ export default class AdbDirectSocketsBackend implements AdbBackend { state: undefined, }; } }), writable: new WrapWritableStream({ }).pipeThrough(new StructDeserializeStream(AdbPacket)), writable: pipeFrom(new WrapWritableStream({ async start() { return { writable, state: undefined, }; } }), }), new AdbPacketSerializeStream()), }; } }
libraries/adb-backend-webusb/package.json +1 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ "dependencies": { "@types/w3c-web-usb": "^1.0.4", "@yume-chan/adb": "^0.0.10", "@yume-chan/struct": "^0.0.10", "tslib": "^2.3.1" }, "devDependencies": { Loading
libraries/adb-backend-webusb/src/backend.ts +24 −16 Original line number Diff line number Diff line import { DuplexStreamFactory, type AdbBackend, type ReadableStream, type ReadableWritablePair, type WritableStream } from '@yume-chan/adb'; import { AdbPacket, AdbPacketSerializeStream, DuplexStreamFactory, pipeFrom, ReadableStream, type AdbBackend, type AdbPacketCore, type AdbPacketInit, type ReadableWritablePair, type WritableStream } from '@yume-chan/adb'; import type { StructAsyncDeserializeStream } from "@yume-chan/struct"; export const WebUsbDeviceFilter: USBDeviceFilter = { classCode: 0xFF, Loading @@ -6,15 +7,15 @@ export const WebUsbDeviceFilter: USBDeviceFilter = { protocolCode: 1, }; export class AdbWebUsbBackendStream implements ReadableWritablePair<Uint8Array, Uint8Array>{ private _readable: ReadableStream<Uint8Array>; export class AdbWebUsbBackendStream implements ReadableWritablePair<AdbPacketCore, AdbPacketInit>{ private _readable: ReadableStream<AdbPacketCore>; public get readable() { return this._readable; } private _writable: WritableStream<Uint8Array>; private _writable: WritableStream<AdbPacketInit>; public get writable() { return this._writable; } public constructor(device: USBDevice, inEndpoint: USBEndpoint, outEndpoint: USBEndpoint) { const factory = new DuplexStreamFactory<Uint8Array, Uint8Array>({ const factory = new DuplexStreamFactory<AdbPacketCore, Uint8Array>({ close: async () => { navigator.usb.removeEventListener('disconnect', handleUsbDisconnect); try { Loading @@ -33,9 +34,13 @@ export class AdbWebUsbBackendStream implements ReadableWritablePair<Uint8Array, navigator.usb.addEventListener('disconnect', handleUsbDisconnect); this._readable = factory.createReadable({ pull: async (controller) => { const result = await device.transferIn(inEndpoint.endpointNumber, inEndpoint.packetSize); const incomingStream: StructAsyncDeserializeStream = { async read(length) { // `ReadableStream<Uin8Array>` don't know how many bytes the consumer need in each `pull`, // But `transferIn(endpointNumber, packetSize)` is much slower than `transferIn(endpointNumber, length)` // So `AdbBackend` is refactored to use `ReadableStream<AdbPacketCore>` directly, // (let each backend deserialize the packets in their own way) const result = await device.transferIn(inEndpoint.endpointNumber, length); // `USBTransferResult` has three states: "ok", "stall" and "babble", // but ADBd on Android won't enter "stall" (halt) state, Loading @@ -44,22 +49,25 @@ export class AdbWebUsbBackendStream implements ReadableWritablePair<Uint8Array, // "babble" just means there is more data to be read. // From spec, the `result.data` always covers the whole `buffer`. const chunk = new Uint8Array(result.data!.buffer); controller.enqueue(chunk); return new Uint8Array(result.data!.buffer); } }; this._readable = factory.createWrapReadable(new ReadableStream<AdbPacketCore>({ async pull(controller) { const value = await AdbPacket.deserialize(incomingStream); controller.enqueue(value); }, }, { highWaterMark: 16 * 1024, size(chunk) { return chunk.byteLength; }, }); })); this._writable = factory.createWritable({ this._writable = pipeFrom(factory.createWritable({ write: async (chunk) => { await device.transferOut(outEndpoint.endpointNumber, chunk); }, }, { highWaterMark: 16 * 1024, size(chunk) { return chunk.byteLength; }, }); }), new AdbPacketSerializeStream()); } } Loading
libraries/adb-backend-webusb/tsconfig.json +3 −0 Original line number Diff line number Diff line Loading @@ -12,6 +12,9 @@ "references": [ { "path": "../adb/tsconfig.build.json" }, { "path": "../struct/tsconfig.json" } ] }