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.
What it is
Section titled “What it is”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.
The wire format
Section titled “The wire format”After the 4-byte iso header:
uint32 sample_count; up to 475 samples in this packetuint32 signature; 0x73676874, "sght"uint32 sample_total; running counter, the drop detectoruint32 reserved;int16 samples[]; interleaved stereo, big-endianEvery 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.
State machine
Section titled “State machine”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.
The stream
Section titled “The stream”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.
The pcm child
Section titled “The pcm child”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.
Bus reset
Section titled “Bus reset”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.
Using it
Section titled “Using it”kldload firewire fwisoundcat /dev/sndstatdd if=/dev/dsp bs=192000 count=5 of=mic.raw # 5 seconds, S16BE stereo