Audio syscalls and /dev/dsp device interface
Goal
Implement syscalls and /dev/dsp device interface for userland audio output, compatible with OSS (Open Sound System) semantics.
Context
Part of #33 (Audio subsystem). This layer exposes the kernel audio core (#383) to userland via a character device (/dev/dsp) and ioctl-based configuration.
Scope
Device Interface
/dev/dsp Character Device
- Create device node in devfs (#136)
- Standard file operations: open, close, write, ioctl, poll
- Multiple open semantics (exclusive vs shared access)
- Non-blocking and blocking modes (O_NONBLOCK flag)
File Operations
open("/dev/dsp", flags)
- Allocate audio stream structure (links to #383 stream manager)
- Set default format (16-bit signed, 48 kHz, stereo)
- Return file descriptor
- Handle exclusive access (return -EBUSY if already opened)
write(fd, buffer, count)
- Copy PCM samples from userland
- Enqueue to stream buffer (ring buffer from #383)
- Block if buffer full (sleep queue)
- Return bytes written or -EAGAIN for non-blocking
ioctl(fd, cmd, arg)
- SNDCTL_DSP_SETFMT: Set sample format (8/16-bit, signed/unsigned)
- SNDCTL_DSP_CHANNELS: Set mono/stereo
- SNDCTL_DSP_SPEED: Set sample rate (11/22/44/48 kHz)
- SNDCTL_DSP_GETOSPACE: Get output buffer space info
- SNDCTL_DSP_RESET: Stop playback and flush buffers
- SNDCTL_DSP_SYNC: Block until all queued samples played
poll(fd, events, timeout)
- Return POLLOUT when buffer has space for writing
- Return POLLERR on errors
- Integrate with kernel poll infrastructure (future: #348)
close(fd)
- Drain remaining buffered samples (or truncate if non-blocking)
- Release stream resources
- Unregister from audio core (#383)
Syscalls
New System Calls
- SYS_AUDIO_OPEN (alternative to open + ioctl)
- SYS_AUDIO_WRITE (optimized write path, optional)
- SYS_AUDIO_IOCTL (maps to generic ioctl)
Note: Can reuse existing syscalls (open/write/ioctl) if /dev/dsp approach is sufficient.
OSS Compatibility
Minimal OSS API Surface
- Format negotiation (AFMT_U8, AFMT_S16_LE)
- Sample rate selection (power-of-2 rates: 11025, 22050, 44100, 48000)
- Channel configuration (mono, stereo)
- Buffer size hints (fragment size)
Implementation Phases
Phase 1: Device Registration (2-3 days)
- Register /dev/dsp in devfs (#136)
- Implement open/close operations
- Allocate/deallocate stream structures
- Handle exclusive access locking
Phase 2: Write Path (3-4 days)
- Implement write() syscall handler
- Copy user buffer to kernel stream buffer (#383)
- Blocking/non-blocking semantics
- Sleep queue integration for buffer-full waits
Phase 3: ioctl Configuration (4-5 days)
- Implement SNDCTL_DSP_* ioctls
- Format/rate/channel validation
- Buffer info queries (GETOSPACE)
- RESET and SYNC operations
Phase 4: Integration and Testing (2-3 days)
- Wire to audio core (#383)
- Test with simple userland tool (tone generator)
- Verify buffer refill timing
- Add error handling and edge cases
Definition of Done
- [ ] /dev/dsp device node created and accessible
- [ ] open() allocates audio stream successfully
- [ ] write() enqueues PCM data to kernel buffers
- [ ] Blocking write() sleeps when buffer full
- [ ] Non-blocking write() returns -EAGAIN appropriately
- [ ] ioctl() configures format, rate, channels
- [ ] close() drains buffers and releases resources
- [ ] Integrates with audio core (#383) stream manager
- [ ] Tested with userland tone generator (#385)
- [ ] OSS-compatible API for Doom's I_InitSound()
Dependencies
- #136 - Device filesystem (devfs) ✅ (CLOSED)
- #96 - File descriptor management ✅ (CLOSED)
- #220 - ioctl syscall infrastructure ✅ (CLOSED)
- #383 - Kernel audio core (CRITICAL - must integrate with stream manager)
- #40 - Condition variables ✅ (for sleep queue)
Risks
- Buffer synchronization: Race conditions between write and mixer
- Latency: High syscall overhead may cause audio stutter
- Format conversion: Mismatch between user format and hardware format
- Blocking semantics: Incorrect sleep/wakeup causes hangs or busy-wait
Timeline
Estimated effort: 2 weeks (11-15 days)
Testing Strategy
- Unit tests: Mock audio core, verify ioctl parsing
- Integration tests: Real audio core, check buffer handoff
- Userland test: Simple tone generator (sine wave at 440 Hz)
- Doom integration: Verify I_InitSound() and I_SubmitSound() work
References
- OSS Programmer's Guide: http://www.opensound.com/pguide/
- Linux OSS emulation:
sound/oss/ - FreeBSD /dev/dsp:
sys/dev/sound/pcm/dsp.c - OSDev Wiki: Sound programming
Related Issues
- Parent: #33 (Audio subsystem)
- Depends on: #136, #96, #220, #383, #40
- Enables: #385 (Userland audio API)
Priority
Medium - Part of Doom audio milestone, blocked by #279
Status
BLOCKED BY #279 (Dynamic IRQ handler registration API)
This issue is part of the audio subsystem implementation for the Doom milestone. It cannot proceed until #279 is complete.
Dependency Chain
#279 (Dynamic IRQ) ← CRITICAL BLOCKER (HIGH priority)
↓
#382 + #383 (Audio driver + core) ← YOU ARE HERE
↓
#384 (Syscalls) → #385 (API) → #386 (Testing)
↓
Doom audio integration
Related Issues
- #33 (Audio subsystem parent) - umbrella issue
- #279 (Dynamic IRQ) - BLOCKS THIS ISSUE
Priority Rationale: Medium priority appropriate for Doom milestone work, but cannot start until HIGH priority #279 is complete.