sound/core/seq/seq_ump_client.c
Source file repositories/reference/linux-study-clean/sound/core/seq/seq_ump_client.c
File Facts
- System
- Linux kernel
- Corpus path
sound/core/seq/seq_ump_client.c- Extension
.c- Size
- 15561 bytes
- Lines
- 551
- 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.
- 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/init.hlinux/slab.hlinux/errno.hlinux/mutex.hlinux/string.hlinux/module.hasm/byteorder.hsound/core.hsound/ump.hsound/seq_kernel.hsound/seq_device.hseq_clientmgr.hseq_system.h
Detected Declarations
struct seq_ump_clientstruct seq_ump_groupstruct seq_ump_input_bufferstruct seq_ump_clientfunction numberfunction seq_ump_input_receivefunction seq_ump_process_eventfunction seq_ump_client_openfunction seq_ump_client_closefunction seq_ump_subscribefunction seq_ump_unsubscribefunction seq_ump_usefunction seq_ump_unusefunction fill_port_infofunction skip_groupfunction seq_ump_group_initfunction update_port_infosfunction create_ump_endpoint_portfunction seq_ump_client_freefunction setup_client_midi_versionfunction setup_client_group_filterfunction handle_group_notifyfunction seq_ump_notify_ep_changefunction seq_ump_notify_fb_changefunction seq_ump_switch_protocolfunction snd_seq_ump_probefunction snd_seq_ump_remove
Annotated Snippet
struct seq_ump_input_buffer {
unsigned char len; /* total length in words */
unsigned char pending; /* pending words */
unsigned char type; /* parsed UMP packet type */
unsigned char group; /* parsed UMP packet group */
u32 buf[4]; /* incoming UMP packet */
};
/* sequencer client, per UMP EP (rawmidi) */
struct seq_ump_client {
struct snd_ump_endpoint *ump; /* assigned endpoint */
int seq_client; /* sequencer client id */
int opened[2]; /* current opens for each direction */
rwlock_t output_lock; /* protects out_rfile output access */
struct snd_rawmidi_file out_rfile; /* rawmidi for output */
struct seq_ump_input_buffer input; /* input parser context */
void *ump_info[SNDRV_UMP_MAX_BLOCKS + 1]; /* shadow of seq client ump_info */
struct work_struct group_notify_work; /* FB change notification */
};
/* number of 32bit words for each UMP message type */
static unsigned char ump_packet_words[0x10] = {
1, 1, 1, 2, 2, 4, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4
};
/* conversion between UMP group and seq port;
* assume the port number is equal with UMP group number (1-based)
*/
static unsigned char ump_group_to_seq_port(unsigned char group)
{
return group + 1;
}
/* process the incoming rawmidi stream */
static void seq_ump_input_receive(struct snd_ump_endpoint *ump,
const u32 *val, int words)
{
struct seq_ump_client *client = ump->seq_client;
struct snd_seq_ump_event ev = {};
if (!client->opened[STR_IN])
return;
if (ump_is_groupless_msg(ump_message_type(*val)))
ev.source.port = 0; /* UMP EP port */
else
ev.source.port = ump_group_to_seq_port(ump_message_group(*val));
ev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS;
ev.flags = SNDRV_SEQ_EVENT_UMP;
memcpy(ev.ump, val, words << 2);
snd_seq_kernel_client_dispatch(client->seq_client,
(struct snd_seq_event *)&ev,
true, 0);
}
/* process an input sequencer event; only deal with UMP types */
static int seq_ump_process_event(struct snd_seq_event *ev, int direct,
void *private_data, int atomic, int hop)
{
struct seq_ump_client *client = private_data;
struct snd_rawmidi_substream *substream;
struct snd_seq_ump_event *ump_ev;
unsigned char type;
int len;
guard(read_lock_irqsave)(&client->output_lock);
substream = client->out_rfile.output;
if (!substream)
return -ENODEV;
if (!snd_seq_ev_is_ump(ev))
return 0; /* invalid event, skip */
ump_ev = (struct snd_seq_ump_event *)ev;
type = ump_message_type(ump_ev->ump[0]);
len = ump_packet_words[type];
if (len > 4)
return 0; // invalid - skip
snd_rawmidi_kernel_write(substream, ev->data.raw8.d, len << 2);
return 0;
}
/* open the rawmidi */
static int seq_ump_client_open(struct seq_ump_client *client, int dir)
{
struct snd_ump_endpoint *ump = client->ump;
struct snd_rawmidi_file rfile = {};
int err;
guard(mutex)(&ump->open_mutex);
if (dir == STR_OUT && !client->opened[dir]) {
err = snd_rawmidi_kernel_open(&ump->core, 0,
Annotation
- Immediate include surface: `linux/init.h`, `linux/slab.h`, `linux/errno.h`, `linux/mutex.h`, `linux/string.h`, `linux/module.h`, `asm/byteorder.h`, `sound/core.h`.
- Detected declarations: `struct seq_ump_client`, `struct seq_ump_group`, `struct seq_ump_input_buffer`, `struct seq_ump_client`, `function number`, `function seq_ump_input_receive`, `function seq_ump_process_event`, `function seq_ump_client_open`, `function seq_ump_client_close`, `function seq_ump_subscribe`.
- 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.