sound/core/oss/linear.c
Source file repositories/reference/linux-study-clean/sound/core/oss/linear.c
File Facts
- System
- Linux kernel
- Corpus path
sound/core/oss/linear.c- Extension
.c- Size
- 5135 bytes
- Lines
- 166
- Domain
- Driver Families
- Bucket
- sound/core
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/time.hsound/core.hsound/pcm.hpcm_plugin.h
Detected Declarations
struct linear_privfunction do_convertfunction convertfunction linear_transferfunction init_datafunction snd_pcm_format_signedfunction snd_pcm_plugin_build_linear
Annotated Snippet
struct linear_priv {
int cvt_endian; /* need endian conversion? */
unsigned int src_ofs; /* byte offset in source format */
unsigned int dst_ofs; /* byte soffset in destination format */
unsigned int copy_ofs; /* byte offset in temporary u32 data */
unsigned int dst_bytes; /* byte size of destination format */
unsigned int copy_bytes; /* bytes to copy per conversion */
unsigned int flip; /* MSB flip for signeness, done after endian conv */
};
static inline void do_convert(struct linear_priv *data,
unsigned char *dst, unsigned char *src)
{
unsigned int tmp = 0;
unsigned char *p = (unsigned char *)&tmp;
memcpy(p + data->copy_ofs, src + data->src_ofs, data->copy_bytes);
if (data->cvt_endian)
tmp = swab32(tmp);
tmp ^= data->flip;
memcpy(dst, p + data->dst_ofs, data->dst_bytes);
}
static void convert(struct snd_pcm_plugin *plugin,
const struct snd_pcm_plugin_channel *src_channels,
struct snd_pcm_plugin_channel *dst_channels,
snd_pcm_uframes_t frames)
{
struct linear_priv *data = (struct linear_priv *)plugin->extra_data;
int channel;
int nchannels = plugin->src_format.channels;
for (channel = 0; channel < nchannels; ++channel) {
char *src;
char *dst;
int src_step, dst_step;
snd_pcm_uframes_t frames1;
if (!src_channels[channel].enabled) {
if (dst_channels[channel].wanted)
snd_pcm_area_silence(&dst_channels[channel].area, 0, frames, plugin->dst_format.format);
dst_channels[channel].enabled = 0;
continue;
}
dst_channels[channel].enabled = 1;
src = src_channels[channel].area.addr + src_channels[channel].area.first / 8;
dst = dst_channels[channel].area.addr + dst_channels[channel].area.first / 8;
src_step = src_channels[channel].area.step / 8;
dst_step = dst_channels[channel].area.step / 8;
frames1 = frames;
while (frames1-- > 0) {
do_convert(data, dst, src);
src += src_step;
dst += dst_step;
}
}
}
static snd_pcm_sframes_t linear_transfer(struct snd_pcm_plugin *plugin,
const struct snd_pcm_plugin_channel *src_channels,
struct snd_pcm_plugin_channel *dst_channels,
snd_pcm_uframes_t frames)
{
if (snd_BUG_ON(!plugin || !src_channels || !dst_channels))
return -ENXIO;
if (frames == 0)
return 0;
#ifdef CONFIG_SND_DEBUG
{
unsigned int channel;
for (channel = 0; channel < plugin->src_format.channels; channel++) {
if (snd_BUG_ON(src_channels[channel].area.first % 8 ||
src_channels[channel].area.step % 8))
return -ENXIO;
if (snd_BUG_ON(dst_channels[channel].area.first % 8 ||
dst_channels[channel].area.step % 8))
return -ENXIO;
}
}
#endif
if (frames > dst_channels[0].frames)
frames = dst_channels[0].frames;
convert(plugin, src_channels, dst_channels, frames);
return frames;
}
static void init_data(struct linear_priv *data,
snd_pcm_format_t src_format, snd_pcm_format_t dst_format)
{
int src_le, dst_le, src_bytes, dst_bytes;
src_bytes = snd_pcm_format_width(src_format) / 8;
Annotation
- Immediate include surface: `linux/time.h`, `sound/core.h`, `sound/pcm.h`, `pcm_plugin.h`.
- Detected declarations: `struct linear_priv`, `function do_convert`, `function convert`, `function linear_transfer`, `function init_data`, `function snd_pcm_format_signed`, `function snd_pcm_plugin_build_linear`.
- Atlas domain: Driver Families / sound/core.
- Implementation status: source implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.