include: one folder per subsystem, and includes that name it
Sixty-five headers sat side by side in include/, so `#include "irq.h"` said nothing about where irq.h was or what it belonged to, and errno.h, stat.h and fcntl.h at the top shadowed the system's for any host tool built with -I./include. They are in folders now -- arch/ core/ fs/ dev/ gfx/ net/ uapi/ (and ldls/ for the Linux driver layer) -- and every include names the folder, as Linux's do: "core/proc.h". Done mechanically and checked the hard way: the kernel built from this tree disassembles identically to the one built from the tree before it. The full image boots, and userland is the same set of programs. Paths in docs and comments follow; docs/guides/layout.md has a table of what is where, and tools/fix-includes.py rewrites old-style includes from the folders in the tree, for code written before this. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
This commit is contained in:
parent
0e39e711f1
commit
a1c965da1e
267 changed files with 1560 additions and 1440 deletions
103
include/dev/audio.h
Normal file
103
include/dev/audio.h
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
#pragma once
|
||||
|
||||
// The audio class, and the engine above it.
|
||||
//
|
||||
// A program that wants to make a sound should be able to open a device, write
|
||||
// samples to it, and stop -- which is what UNIX audio has always been, and
|
||||
// what this is. `/dev/dsp`, PCM in, `write()`, and a handful of ioctls to say
|
||||
// what the samples are. No server, no session bus, no protocol.
|
||||
//
|
||||
// The shape is the display class's, for the same reason: a consumer asks for
|
||||
// "the audio device" and gets whatever is bound, so adding a second driver is
|
||||
// not an edit to every caller. Found with device_find_class(DEVCLASS_AUDIO).
|
||||
//
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
// **What the engine is for, and what it is not yet.**
|
||||
//
|
||||
// AudioEngine owns everything above a driver that is not specific to a chip:
|
||||
// what format the stream is in, how many bytes the hardware can take, and what
|
||||
// a write() does when it cannot take them all. That is genuinely shared -- a
|
||||
// second driver should not re-implement "block until there is room".
|
||||
//
|
||||
// It is deliberately *one stream*. Mixing several programs into one device is
|
||||
// a real feature with a real design behind it, and building it before anything
|
||||
// plays a single sound would be the mistake docs/plan/1.0.md warns about: work
|
||||
// that exists and is connected to nothing. The second program that wants to
|
||||
// play at the same time is what should cause it to be written.
|
||||
|
||||
struct device;
|
||||
|
||||
// Interleaved signed 16-bit little-endian, which is what every PC audio chip
|
||||
// takes natively and what a WAV file already contains. Others exist and none
|
||||
// of them is needed to make a sound; converting in the kernel to satisfy a
|
||||
// caller that could have converted first is not an obvious trade.
|
||||
#define AUDIO_FMT_S16LE 16
|
||||
|
||||
struct audio_format {
|
||||
unsigned int rate; // frames per second -- 48000, 44100
|
||||
unsigned int channels; // 1 mono, 2 stereo
|
||||
unsigned int bits; // AUDIO_FMT_S16LE
|
||||
};
|
||||
|
||||
struct audio_ops {
|
||||
// Take this format, or report what the hardware will do instead by writing
|
||||
// back into `f` and returning 0. Returning negative means it cannot play at
|
||||
// all. A driver that only does 48 kHz stereo says so here rather than
|
||||
// failing a write() later, which is the difference between a program that
|
||||
// adapts and a program that gets silence.
|
||||
int (*configure)(struct device *, struct audio_format *f);
|
||||
|
||||
// Bytes that can be queued right now without waiting. The engine uses this
|
||||
// to decide whether a write() has to block, so a driver that returns a
|
||||
// hardware-accurate number is a driver whose write() latency is honest.
|
||||
int (*space)(struct device *);
|
||||
|
||||
// Queue PCM. Returns bytes accepted, which may be fewer than offered and
|
||||
// may be zero; the engine handles the remainder. Never blocks.
|
||||
int (*queue)(struct device *, const void *pcm, int bytes);
|
||||
|
||||
// Start the stream if it is not running. Called by the engine once there is
|
||||
// something to play, rather than at open: a device left running with an
|
||||
// empty ring plays whatever was in it, which on real hardware is a loop of
|
||||
// the last buffer and sounds exactly as bad as it reads.
|
||||
void (*start)(struct device *);
|
||||
|
||||
// Stop, and discard anything queued.
|
||||
void (*stop)(struct device *);
|
||||
|
||||
// Bytes still to be played. Zero means the hardware has finished. The
|
||||
// engine polls this for SNDCTL_DSP_SYNC rather than a driver growing its
|
||||
// own wait loop.
|
||||
int (*pending)(struct device *);
|
||||
};
|
||||
|
||||
// --- what the kernel uses --------------------------------------------------
|
||||
|
||||
struct device *audio_get(void);
|
||||
int audio_configure(struct audio_format *f); // 0, or negative
|
||||
int audio_write(const void *pcm, int bytes); // bytes queued, or negative
|
||||
void audio_drain(void);
|
||||
void audio_stop(void);
|
||||
|
||||
// --- what userspace uses ---------------------------------------------------
|
||||
//
|
||||
// OSS numbering, which is the one every UNIX audio program already knows and
|
||||
// the only reason to invent a different set would be to make ports harder.
|
||||
// These four are the whole interface a tone generator or a WAV player needs.
|
||||
|
||||
#define SNDCTL_DSP_SPEED 0xC0045002 // int in/out: sample rate
|
||||
#define SNDCTL_DSP_CHANNELS 0xC0045006 // int in/out: 1 or 2
|
||||
#define SNDCTL_DSP_SETFMT 0xC0045005 // int in/out: AFMT_S16_LE
|
||||
#define SNDCTL_DSP_SYNC 0x00005001 // wait for the queue to drain
|
||||
#define SNDCTL_DSP_GETOSPACE 0x8010500C // struct audio_buf_info out
|
||||
#define SNDCTL_DSP_RESET 0x00005000 // stop, discard
|
||||
|
||||
#define AFMT_S16_LE 0x00000010
|
||||
|
||||
struct audio_buf_info {
|
||||
int fragments; // how many whole fragments are free
|
||||
int fragstotal; // how many there are in total
|
||||
int fragsize; // bytes in one
|
||||
int bytes; // free bytes, which is the number that matters
|
||||
};
|
||||
Loading…
Reference in a new issue