sound/pci/ca0106/ca_midi.c
Source file repositories/reference/linux-study-clean/sound/pci/ca0106/ca_midi.c
File Facts
- System
- Linux kernel
- Corpus path
sound/pci/ca0106/ca_midi.c- Extension
.c- Size
- 7333 bytes
- Lines
- 282
- Domain
- Driver Families
- Bucket
- sound/pci
- 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.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/spinlock.hsound/core.hsound/rawmidi.hca_midi.h
Detected Declarations
function ca_midi_clear_rxfunction ca_midi_interruptfunction scoped_guardfunction scoped_guardfunction ca_midi_cmdfunction scoped_guardfunction ca_midi_input_openfunction ca_midi_output_openfunction ca_midi_input_closefunction ca_midi_output_closefunction scoped_guardfunction ca_midi_input_triggerfunction ca_midi_output_triggerfunction scoped_guardfunction ca_midi_freefunction ca_rmidi_freefunction ca_midi_init
Annotated Snippet
if ((status & midi->ipr_rx) && ca_midi_input_avail(midi)) {
if (!(midi->midi_mode & CA_MIDI_MODE_INPUT)) {
ca_midi_clear_rx(midi);
} else {
byte = ca_midi_read_data(midi);
if (midi->substream_input)
snd_rawmidi_receive(midi->substream_input, &byte, 1);
}
}
}
scoped_guard(spinlock, &midi->output_lock) {
if ((status & midi->ipr_tx) && ca_midi_output_ready(midi)) {
if (midi->substream_output &&
snd_rawmidi_transmit(midi->substream_output, &byte, 1) == 1) {
ca_midi_write_data(midi, byte);
} else {
midi->interrupt_disable(midi, midi->tx_enable);
}
}
}
}
static void ca_midi_cmd(struct snd_ca_midi *midi, unsigned char cmd, int ack)
{
int timeout, ok;
scoped_guard(spinlock_irqsave, &midi->input_lock) {
ca_midi_write_data(midi, 0x00);
/* ca_midi_clear_rx(midi); */
ca_midi_write_cmd(midi, cmd);
if (ack) {
ok = 0;
timeout = 10000;
while (!ok && timeout-- > 0) {
if (ca_midi_input_avail(midi)) {
if (ca_midi_read_data(midi) == midi->ack)
ok = 1;
}
}
if (!ok && ca_midi_read_data(midi) == midi->ack)
ok = 1;
} else {
ok = 1;
}
}
if (!ok)
pr_err("ca_midi_cmd: 0x%x failed at 0x%x (status = 0x%x, data = 0x%x)!!!\n",
cmd,
midi->get_dev_id_port(midi->dev_id),
ca_midi_read_stat(midi),
ca_midi_read_data(midi));
}
static int ca_midi_input_open(struct snd_rawmidi_substream *substream)
{
struct snd_ca_midi *midi = substream->rmidi->private_data;
if (snd_BUG_ON(!midi->dev_id))
return -ENXIO;
scoped_guard(spinlock_irqsave, &midi->open_lock) {
midi->midi_mode |= CA_MIDI_MODE_INPUT;
midi->substream_input = substream;
if (midi->midi_mode & CA_MIDI_MODE_OUTPUT)
return 0;
}
ca_midi_cmd(midi, midi->reset, 1);
ca_midi_cmd(midi, midi->enter_uart, 1);
return 0;
}
static int ca_midi_output_open(struct snd_rawmidi_substream *substream)
{
struct snd_ca_midi *midi = substream->rmidi->private_data;
if (snd_BUG_ON(!midi->dev_id))
return -ENXIO;
scoped_guard(spinlock_irqsave, &midi->open_lock) {
midi->midi_mode |= CA_MIDI_MODE_OUTPUT;
midi->substream_output = substream;
if (midi->midi_mode & CA_MIDI_MODE_INPUT)
return 0;
}
ca_midi_cmd(midi, midi->reset, 1);
ca_midi_cmd(midi, midi->enter_uart, 1);
return 0;
}
static int ca_midi_input_close(struct snd_rawmidi_substream *substream)
Annotation
- Immediate include surface: `linux/spinlock.h`, `sound/core.h`, `sound/rawmidi.h`, `ca_midi.h`.
- Detected declarations: `function ca_midi_clear_rx`, `function ca_midi_interrupt`, `function scoped_guard`, `function scoped_guard`, `function ca_midi_cmd`, `function scoped_guard`, `function ca_midi_input_open`, `function ca_midi_output_open`, `function ca_midi_input_close`, `function ca_midi_output_close`.
- Atlas domain: Driver Families / sound/pci.
- 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.