sound/usb/line6/playback.c
Source file repositories/reference/linux-study-clean/sound/usb/line6/playback.c
File Facts
- System
- Linux kernel
- Corpus path
sound/usb/line6/playback.c- Extension
.c- Size
- 11412 bytes
- Lines
- 439
- Domain
- Driver Families
- Bucket
- sound/usb
- 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.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/slab.hsound/core.hsound/pcm.hsound/pcm_params.hcapture.hdriver.hpcm.hplayback.h
Detected Declarations
function Copyrightfunction create_impulse_test_signalfunction add_monitor_signalfunction submit_audio_out_urbfunction line6_submit_audio_out_all_urbsfunction audio_out_callbackfunction snd_line6_playback_openfunction snd_line6_playback_closefunction line6_create_audio_out_urbs
Annotated Snippet
if (fsize == 0) {
int n;
line6pcm->out.count += frame_increment;
n = line6pcm->out.count / frame_factor;
line6pcm->out.count -= n * frame_factor;
fsize = n;
}
fsize *= bytes_per_frame;
fout->offset = urb_size;
fout->length = fsize;
urb_size += fsize;
}
if (urb_size == 0) {
/* can't determine URB size */
dev_err(line6pcm->line6->ifcdev, "driver bug: urb_size = 0\n");
return -EINVAL;
}
urb_frames = urb_size / bytes_per_frame;
urb_out->transfer_buffer =
line6pcm->out.buffer +
index * LINE6_ISO_PACKETS * line6pcm->max_packet_size_out;
urb_out->transfer_buffer_length = urb_size;
urb_out->context = line6pcm;
if (test_bit(LINE6_STREAM_PCM, &line6pcm->out.running) &&
!test_bit(LINE6_FLAG_PAUSE_PLAYBACK, &line6pcm->flags)) {
struct snd_pcm_runtime *runtime =
get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK)->runtime;
if (line6pcm->out.pos + urb_frames > runtime->buffer_size) {
/*
The transferred area goes over buffer boundary,
copy the data to the temp buffer.
*/
int len;
len = runtime->buffer_size - line6pcm->out.pos;
if (len > 0) {
memcpy(urb_out->transfer_buffer,
runtime->dma_area +
line6pcm->out.pos * bytes_per_frame,
len * bytes_per_frame);
memcpy(urb_out->transfer_buffer +
len * bytes_per_frame, runtime->dma_area,
(urb_frames - len) * bytes_per_frame);
} else
dev_err(line6pcm->line6->ifcdev, "driver bug: len = %d\n",
len);
} else {
memcpy(urb_out->transfer_buffer,
runtime->dma_area +
line6pcm->out.pos * bytes_per_frame,
urb_out->transfer_buffer_length);
}
line6pcm->out.pos += urb_frames;
if (line6pcm->out.pos >= runtime->buffer_size)
line6pcm->out.pos -= runtime->buffer_size;
change_volume(urb_out, line6pcm->volume_playback,
bytes_per_frame);
} else {
memset(urb_out->transfer_buffer, 0,
urb_out->transfer_buffer_length);
}
spin_lock_nested(&line6pcm->in.lock, SINGLE_DEPTH_NESTING);
if (line6pcm->prev_fbuf) {
if (test_bit(LINE6_STREAM_IMPULSE, &line6pcm->out.running)) {
create_impulse_test_signal(line6pcm, urb_out,
bytes_per_frame);
if (test_bit(LINE6_STREAM_PCM, &line6pcm->in.running)) {
line6_capture_copy(line6pcm,
urb_out->transfer_buffer,
urb_out->
transfer_buffer_length);
line6_capture_check_period(line6pcm,
urb_out->transfer_buffer_length);
}
} else {
if (!(line6pcm->line6->properties->capabilities & LINE6_CAP_HWMON)
&& line6pcm->out.running && line6pcm->in.running)
add_monitor_signal(urb_out, line6pcm->prev_fbuf,
line6pcm->volume_monitor,
Annotation
- Immediate include surface: `linux/slab.h`, `sound/core.h`, `sound/pcm.h`, `sound/pcm_params.h`, `capture.h`, `driver.h`, `pcm.h`, `playback.h`.
- Detected declarations: `function Copyright`, `function create_impulse_test_signal`, `function add_monitor_signal`, `function submit_audio_out_urb`, `function line6_submit_audio_out_all_urbs`, `function audio_out_callback`, `function snd_line6_playback_open`, `function snd_line6_playback_close`, `function line6_create_audio_out_urbs`.
- Atlas domain: Driver Families / sound/usb.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
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.