fwcam(4)
Source: sys/dev/firewire/fwcam.c, fwcam.h, with shared iso plumbing
in fw_helpers.h. Registers with video(4).
What it is
Section titled “What it is”A driver for IIDC/DCAM cameras, the 1394 Trade Association’s camera
protocol. It matches any unit directory with spec id 0x00a02d and an
IIDC software version (1.04, 1.20, 1.30), no vendor list. Control is
async quadlet reads and writes into a register block; video arrives as
isochronous packets that get assembled into frames and handed to
video(4), which owns /dev/videoN.
One CROM wrinkle earns a comment in the code: the command base register offset normally sits in the unit directory, but the Apple iSight buries it inside a nested logical unit directory, so the search recurses two levels deep.
Lazy bring-up
Section titled “Lazy bring-up”Attach touches no hardware. The camera is powered on and its capabilities read on first open, from a taskqueue, because power-on can take five seconds of polling and nobody wants that in attach.
Openers sleep up to ten seconds waiting for PROBING to resolve. Capabilities are inquiry bitmaps read from the camera itself: supported formats, per-format modes, per-mode frame rates, and a feature matrix from brightness to focus, each feature a live CSR with present, auto, manual, min and max bits.
Starting a stream
Section titled “Starting a stream”The enable sequence follows the IIDC spec’s ordering, with one quirk:
- Write format, mode, frame rate.
- Read the error status register; if the camera flags the combination, fail with EINVAL before touching ISO_EN.
- Write the iso channel and speed.
- Write ISO_EN. If this returns EIO, power the camera on again and retry once: cameras with a closed lens cover power down the sensor and NAK the enable.
- Only then enable the host IR DMA context.
There is no IRM bandwidth or channel allocation; the channel is the
hw.firewire.fwcam.iso_channel tunable (default 0), and the OHCI
context filters on it in hardware. 256 mbuf-cluster chunks ride the
receive ring.
Frame assembly
Section titled “Frame assembly”Packets arrive via the firewire taskqueue, not hard interrupt, which is why the handler can take a regular mutex and memcpy entire frames.
If userland has no buffer queued when a frame completes, the frame is dropped silently: video(4)‘s acquire returns NULL and only the driver’s counter notices.
Bus reset, by construction
Section titled “Bus reset, by construction”The FireWire core delivers post_busreset callbacks only to bus-level
children, and fwcam is a unit child, so it never hears about resets.
What that means in practice:
- Register access self-heals: the node id is re-read from the device structure on every transaction, and bus explore updates it in place.
- A live stream does not. The IIDC spec has cameras clear ISO_EN on reset, and there is no re-arm path: the stream goes silent, state stays STREAMING, and userland has to stop and restart. No watchdog catches the stall.
- A camera that disappears ages out of the bus and the unit child is detached properly.
Teardown ordering
Section titled “Teardown ordering”Stop claims ownership by atomically setting dma_ch to -1, disables
host DMA first, writes ISO_EN off at the camera, then sleeps until the
in-flight input handler drains: the handler sees the dead dma_ch and
skips its re-arm. Only then do the ring and frame buffer go away.
Using it
Section titled “Using it”kldload firewire fwcam videols /dev/video* # the camera is a video(4) nodeControls map to V4L2 ids: brightness, exposure, sharpness, white balance, hue, saturation, gamma, gain, focus. Each get and set is a live quadlet transaction to the feature CSR.