webmuxd is a WebUSB implementation of Apple's usbmuxd protocol, compatible with libimobiledevice/usbmuxd.
Yarn:
yarn add webmuxd
NPM:
npm add webmuxd
webmuxd has three layers, each usable on its own:
MobileDevicefinds the usbmux interface on an Apple device over WebUSB, claims it and pumps its bulk endpoints.UsbMuxandTcpChannelare a TypeScript port of the host side ofusbmuxd: version negotiation, the setup packet, sequence numbers, packet reassembly, and the minimal TCP (SYN / SYN-ACK / ACK, prompt ACKs, window flow control) that the device expects. With them a page can talk to device services such aslockdownddirectly.RemoteChannelconnects devices to a server such as go-webmuxd over a WebSocket, using the protobuf protocol insrc/remote/transport.proto.
import MobileDevice, { CONSOLE_LOGGER } from 'webmuxd';
MobileDevice.logger = CONSOLE_LOGGER;
const device = await MobileDevice.selectDevice();
const mux = await device.startMux();
const lockdown = await mux.connect(62078);
lockdown.onData = (data) => console.log('lockdownd replied', data);
lockdown.write(request); // length-prefixed plistimport MobileDevice, { RemoteChannel } from 'webmuxd';
const remote = new RemoteChannel({ url: 'wss://example.com/v1/device', reopen: true, mode: 'raw' });
for (const device of await MobileDevice.getDevices()) {
await remote.bindDevice(device);
}RemoteChannel has two modes, chosen per device in the DeviceConnected message:
raw(the default) is the original protocol thatgo-webmuxdspeaks today: the server runs usbmux and the browser relays bytes. The browser now reassembles USB transfers so everyDataFromDevicecarries complete mux packets.muxruns usbmux in the browser. The server opens channels to device ports withOpenChanneland exchanges stream bytes withChannelData, so framing and ACKs never cross the WebSocket. This needs server support.
The example app in webmuxd-example shows the pieces wired into a UI.
If you wish to create your own build it's rather simple:
yarn run build
yarn test, yarn lint and yarn typecheck run the same checks as CI. After editing transport.proto, regenerate
src/remote/transport.ts with yarn proto (needs protoc on your PATH).
The simplest way to build, develop and diagnose is using the XHC20 USB capture on macOS, and optionally demuxusb
https://www.umpah.net/how-to-sniff-usb-traffic-reverse-engineer-usb-device-interactions/
Using a Chromebook as an endpoint:
https://blog.rickmark.me/puppeteer-with-chromeos/
This project is happy to accept PRs and other contributions. It is free for commercial use under the MIT license, I would love to see it credited if so!
Done:
- Handle all
usbmuxdframing and ACKs in script to reduce RTT (UsbMux,TcpChannel) - Standardize the WebSocket protocol and move it from
webmuxd-exampleintowebmuxd(MobileDevice,RemoteChannel,transport.proto/transport.ts)
Still open, outside this package:
- Support
muxmode ingo-webmuxd, and switchwebmuxd-exampleto depend on this package - Factor out "common UI elements" to
webmuxd-ui- Device Picker
- Device Info
- Improve
go-webmuxdas a multi-session "meet me" service