omdrop-owl Teaches a Linux Wi-Fi Card to Meet AirDrop Halfway

The protocol was reverse engineered years ago. The hard part was a radio that refuses to change channels.

9 min read • View on GitHub • More from t4t5

A wide editorial engraving of a railway switchyard at night. Six parallel tracks curve through the yard, and most locomotives switch freely between them. One locomotive at the left is bolted to a single straight track with heavy iron brackets, its wheels locked to the rails. A signalman stands beside it with a clipboard, copying a timetable from an express train passing mid-journey. The scene stands for AWDL's channel-hopping schedule and the fixed-radio workaround that follows one peer's timetable instead of the sync master's.
AWDL expects a radio that changes tracks on a 16-slot timetable. omdrop-owl bolts one locomotive to a single track and copies the schedule of the train that is actually moving.
Key Takeaways

The 27 kB/s Problem

The most important number in omdrop-owl is not in the README. It sits in a code comment inside patches/owl-03-fixed-radio.patch, and it reads like a lab note left for whoever comes next.

Two Apple devices were nearby. One was the sync master, an idle iPad advertising channel 6 in two of its sixteen slots. The other was an iPhone in the middle of a transfer, advertising a sequence packed with channel 149. OWL's default behavior is to follow the master. That meant meeting an idle device on a quiet channel, and the throughput collapsed to 27 kB/s.

omdrop-owl's -F flag, the fixed radio, is the workaround. It pins the Wi-Fi card to a single channel and gives up on hopping. That should be strictly worse: hopping exists so peers can meet each other across the band. But the channel the card is pinned to is not chosen to suit the peers, so the schedule has to be rebuilt around them. Following the phone instead of the master is what turns 27 kB/s into 150.

AWDL, Briefly, and Who Actually Built It

AWDL is Apple's peer-to-peer Wi-Fi link, the transport underneath AirDrop. It does not use a separate radio. It borrows the same chip that connects to your access point and switches it onto a shared schedule, a repeating series of sixteen time slots, so two devices know when to be on the same channel at the same time.

On Apple hardware the chip does the hopping in firmware. On everything else, that is the wall. The traditional Linux path relied on Broadcom firmware modifications, which is why AirDrop on Linux has always looked like a hardware compatibility problem more than a software one.

The software problem was solved years ago. Seemoo Lab, the Secure Mobile Networking Lab at TU Darmstadt, reverse engineered AirDrop and released OpenDrop, then built OWL, an open implementation of AWDL itself. omdrop, by brentkearney, built the AirDrop workflow on top. omdrop-owl is the newest layer: it patches OWL and wires it into omdrop so a non-Apple card can carry the traffic.

The radio half of omdrop for machines without Apple's Broadcom Wi-Fi. AWDL runs in userspace through OWL on a monitor interface, and omdrop's own receiver and sender run over it unchanged.

t4t5, Project author · t4t5/omdrop-owl README

It is worth saying plainly, because a wave of social posts did not: this is not a from-scratch reverse engineering of AirDrop. The Tildes thread that greeted the launch asked the obvious question, and it deserves a straight answer.

I'm not sure how this compares to https://github.com/seemoo-lab/opendrop, which is the original AirDrop reverse engineered implementation that this is based on.

Tildes commenter, Community commenter · Tildes discussion

Follow the Phone, Not the Master

The merge lives in awdl_adopt_chanseq, the function that decides which peer's channel schedule to adopt. Normally it copies the sync master's advertised sequence. With -F, it does something else.

It scans every nearby peer. For each one it computes a phase offset, the difference between that peer's sync and ours, and folds it into a signed range around zero. If the offset falls outside plus or minus 16 time units, the peer is skipped. This is the gate: only peers close enough in phase to share a schedule are considered.

The modular arithmetic that does the folding is the part worth staring at.

off_tu = ((p->sync_offset / 1024) % 1024 + 1024 + 512) % 1024 - 512;
if (off_tu > 16 || off_tu < -16) continue;
for (int i = 0; i < AWDL_CHANSEQ_LENGTH; i++) {
    if (!awdl_chan_num(seq[i], src->sequence_enc) &&
        awdl_chan_num(p->sequence[i], p->sequence_enc) == ours) {
        seq[i] = p->sequence[i];
        kept++;
    }
}

The +512 and -512 shift the window so that peers just on either side of the 1024 boundary compare correctly instead of appearing a full cycle apart. Then, for each of the sixteen slots, the code copies the peer's channel only if our slot is empty and the peer's slot is on the channel we are pinned to.

The channel sequence merge: how a fixed-radio card decides which peer's schedule to copy, and why the sync master is the wrong default.

The comment is explicit about the limits. Bytes are only ever copied from a peer's own sequence, and only from peers whose slots line up with ours. A peer from another cluster means a different slot at the same index. The phase gate and the encoding check are what enforce that.

One companion change matters. With a fixed radio, the multicast guard shrinks from AWDL_MULTICAST_GUARD_TU to AWDL_UNICAST_GUARD_TU. The wide guard normally avoids the first and last availability windows of a slot so late-arriving peers still catch the frame. A fixed radio has no such luxury, because the first window may be all a peer ever gets.

The Interoperability Tax

Not every patch is an optimization. Several exist because real Apple devices do things the spec does not describe, and strict code rejects them.

The A-MSDUs patch is the sharpest. It is a bounds check in a parser fed by untrusted over-the-air frames, and it ships with its own test. The padding patch is quieter but just as load-bearing: a strict parser silently drops a real phone.

The Product Is the Glue

Here is the surprise. For a project people described as reverse engineering AirDrop, the repository owns almost no protocol code. It owns a pins file with two commit hashes, nine patches, a staging script, and four packaging paths.

The staging script is where the most opinionated decision lives. omdrop-awdl is GPL-2.0-only, so rather than vendor it, the script fetches it at a pinned commit and copies a fixed list of files.

A close-up editorial engraving of a single wooden spool of thread on a workbench. One continuous thread leaves the spool and splits into four separate strands, each running to a different loom in the soft background. Each loom carries a small shuttle marked with a different symbol, and a paper tag is pinned to the spool with two short handwritten lines. The image stands for a single pins file fanning out to four packaging targets from one source of truth.
One spool, four looms. A single set of pinned commit hashes fans out to AUR, Debian, Fedora, and Nix.

Two smaller lessons are baked into the same script. Files are replaced individually rather than as a directory, because running the tools as root leaves a root-owned __pycache__ that a user cannot delete. And the copied set is deliberately limited to code that talks to awdl0 over sockets or to BlueZ over D-Bus. None of it touches Broadcom firmware.

One set of pins fans out to AUR, Debian, Fedora, and Nix. The build script even asks the compiler where its headers are instead of checking /usr/include, because Nix keeps them elsewhere. That is the whole product thesis: one source of truth, four distros, and a patch series that is the only authorized divergence from upstream.

Where It Sits

These projects are layers in one stack, not competitors. Reading the table as a leaderboard misses the point.

ProjectWhat layer it solvesHardware assumptionConcurrent Wi-Fi + AWDLTested cardsLicense
omdrop-owlRadio backend for omdropNon-Apple cards via userspace OWL on a monitor interfaceConcurrent mode works on the AP's channelMT7925Shell + patches
Broadcom omdrop backend (brcmfmac-awdl-dkms)The sibling radio pathRequires Broadcom firmware modificationConflicts with omdrop-owl; only one installed at a timeBroadcom hardwareKernel module + firmware
OpenDropFull AirDrop implementation and the original reverse engineeringProtocol and software layer, not a radio backendNot its concernN/AGPL
OWLThe AWDL implementation omdrop-owl patchesSupplies the network layer; does not ship an AirDrop clientNot its concernN/AGPL
omdrop / omdrop-pluginThe user-facing workflow (sender, receiver, panel integration)Supplies the software that omdrop-owl gives a radioNot its concernN/AGPL-2.0

What It Doesn't Do

The README is unusually honest about the edges. One card is tested, the MediaTek MT7925. Every other driver is gated behind /etc/omdrop/allow-untested and runs only after you opt in.

Shared mode, where AWDL and your normal Wi-Fi coexist, requires the access point to sit on channel 6, 44, or 149. Receiving is faster than sending, roughly 1.3 MB/s against 490 kB/s, and the project attributes the gap to how the card paces injected frames. The MT7925 may need a reconnect after the monitor interface is torn down.

And the credit line stands. This is integration and hardware-specific engineering layered on years of prior reverse engineering. The Tildes thread was right to ask, and the README was right to answer.