sound/firewire/fireworks/fireworks_hwdep.c
Source file repositories/reference/linux-study-clean/sound/firewire/fireworks/fireworks_hwdep.c
File Facts
- System
- Linux kernel
- Corpus path
sound/firewire/fireworks/fireworks_hwdep.c- Extension
.c- Size
- 7356 bytes
- Lines
- 314
- Domain
- Driver Families
- Bucket
- sound/firewire
- 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.
- Touches user memory; correctness depends on fault-safe copying and privilege boundary handling.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
fireworks.h
Detected Declarations
function Copyrightfunction hwdep_read_lockedfunction scoped_guardfunction hwdep_readfunction hwdep_writefunction hwdep_pollfunction hwdep_get_infofunction hwdep_lockfunction hwdep_unlockfunction hwdep_releasefunction hwdep_ioctlfunction hwdep_compat_ioctlfunction snd_efw_create_hwdep_device
Annotated Snippet
while (length > 0) {
till_end = snd_efw_resp_buf_size -
(unsigned int)(pull_ptr - efw->resp_buf);
till_end = min_t(unsigned int, length, till_end);
spin_unlock_irq(&efw->lock);
if (copy_to_user(buf, pull_ptr, till_end))
return -EFAULT;
spin_lock_irq(&efw->lock);
pull_ptr += till_end;
if (pull_ptr >= efw->resp_buf + snd_efw_resp_buf_size)
pull_ptr -= snd_efw_resp_buf_size;
length -= till_end;
buf += till_end;
count += till_end;
remained -= till_end;
}
}
/*
* All of tasks can read from the buffer nearly simultaneously, but the
* last position for each task is different depending on the length of
* given buffer. Here, for simplicity, a position of buffer is set by
* the latest task. It's better for a listening application to allow one
* thread to read from the buffer. Unless, each task can read different
* sequence of responses depending on variation of buffer length.
*/
efw->pull_ptr = pull_ptr;
spin_unlock_irq(&efw->lock);
return count;
}
static long
hwdep_read_locked(struct snd_efw *efw, char __user *buf, long count,
loff_t *offset)
{
union snd_firewire_event event = {
.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS,
};
scoped_guard(spinlock_irq, &efw->lock) {
event.lock_status.status = (efw->dev_lock_count > 0);
efw->dev_lock_changed = false;
}
count = min_t(long, count, sizeof(event.lock_status));
if (copy_to_user(buf, &event, count))
return -EFAULT;
return count;
}
static long
hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count,
loff_t *offset)
{
struct snd_efw *efw = hwdep->private_data;
DEFINE_WAIT(wait);
bool dev_lock_changed;
bool queued;
spin_lock_irq(&efw->lock);
dev_lock_changed = efw->dev_lock_changed;
queued = efw->push_ptr != efw->pull_ptr;
while (!dev_lock_changed && !queued) {
prepare_to_wait(&efw->hwdep_wait, &wait, TASK_INTERRUPTIBLE);
spin_unlock_irq(&efw->lock);
schedule();
finish_wait(&efw->hwdep_wait, &wait);
if (signal_pending(current))
return -ERESTARTSYS;
spin_lock_irq(&efw->lock);
dev_lock_changed = efw->dev_lock_changed;
queued = efw->push_ptr != efw->pull_ptr;
}
spin_unlock_irq(&efw->lock);
if (dev_lock_changed)
count = hwdep_read_locked(efw, buf, count, offset);
else if (queued)
Annotation
- Immediate include surface: `fireworks.h`.
- Detected declarations: `function Copyright`, `function hwdep_read_locked`, `function scoped_guard`, `function hwdep_read`, `function hwdep_write`, `function hwdep_poll`, `function hwdep_get_info`, `function hwdep_lock`, `function hwdep_unlock`, `function hwdep_release`.
- Atlas domain: Driver Families / sound/firewire.
- Implementation status: source implementation candidate.
- This snippet crosses the user/kernel memory boundary; validate fault handling and access checks before translating the pattern.
- 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.