Skip to content

fwisound(4)

Source: sys/dev/firewire/fwisound.c, fwisound.h, fwisound_pcm.c. Protocol per Clemens Ladisch’s reverse engineering for the Linux isight ALSA driver.

The FireWire iSight is one physical device with two unit directories: the camera unit that fwcam(4) binds, and an Apple audio unit (spec id 0x000a27, version 0x000010) that this driver binds. The audio side is not AMDTP, not IEC 61883, not anything with a spec sheet. It is a private Apple protocol: raw isochronous packets with a 16-byte header, fixed 48 kHz stereo S16 big-endian.

The driver splits in two: fwisound owns the FireWire side, and a pcm child glues it into sound(4), so the microphone is just /dev/dsp with one recording channel.

After the 4-byte iso header:

uint32 sample_count; up to 475 samples in this packet
uint32 signature; 0x73676874, "sght"
uint32 sample_total; running counter, the drop detector
uint32 reserved;
int16 samples[]; interleaved stereo, big-endian

Every packet is validated in a cascade: length, signature, sample count, payload size. Any failure is a silent drop. The sample_total counter is the only continuity mechanism: a mismatch against the expected running total bumps a dropped counter and resyncs. Dropped audio is not zero-filled; the ring simply advances less.

Unlike fwcam there is no PROBING wait state: the probe is fire-and-forget at attach, and nothing sleeps on it.

The start/stop task pair exists because of context: newpcm’s channel_trigger must not sleep, and starting the stream means FireWire register writes with two-second timeouts. So trigger flips a running flag and enqueues; the tasks do the sleeping. Stop drains the start task first, so a queued start can never land after the stop.

Start writes the channel and speed into the device’s TX config register (the device transmits, the host receives), then sets the audio enable bit, then arms the host IR context: 64 chunks on channel 1 by default, deliberately distinct from fwcam’s channel 0 so video and audio coexist on one cable.

The ring copy runs with no lock held at all: the handler snapshots the channel pointer and trusts the running flag, and channel_free synchronizes only by draining the stop task, which itself waits out any in-flight handler before the buffer can be freed.

One PCMDIR_REC channel, capabilities pinned to exactly S16BE / 2ch / 48000: set-format rejects anything else and set-speed is hardwired. getptr is a monotonic byte counter modulo the buffer. No playback, no mixer yet; the gain and mute registers are read at probe and stored, unwired.

Same architecture as fwcam: unit children get no reset callbacks. The host side keeps receiving (channel filtering survives renumbering), and register writes self-heal via the per-transaction node id. But if the iSight stops transmitting across the reset, the stream stalls in STREAMING with hw_ptr frozen. The sample_total resync is the only reset-adjacent recovery: a device that resumes with a discontinuity is absorbed as one big drop.

Terminal window
kldload firewire fwisound
cat /dev/sndstat
dd if=/dev/dsp bs=192000 count=5 of=mic.raw # 5 seconds, S16BE stereo