Skip to content

Commit 4025f0e

Browse files
committed
ALSA: seq: ump: Create UMP Endpoint port for broadcast
Create a sequencer port for broadcasting the all group inputs at the port number 0. This corresponds to a UMP Endpoint connection; application can read all UMP events from this port no matter which group the UMP packet belongs to. Unlike seq ports for other UMP groups, a UMP Endpoint port has no SND_SEQ_PORT_TYPE_MIDI_GENERIC bit, so that it won't be treated as a normal MIDI 1.0 device from legacy applications. The port is named as "MIDI 2.0" to align with representations on other operation systems. Reviewed-by: Jaroslav Kysela <perex@perex.cz> Link: https://lore.kernel.org/r/20230523075358.9672-34-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
1 parent 81fd444 commit 4025f0e

1 file changed

Lines changed: 60 additions & 0 deletions

File tree

sound/core/seq/seq_ump_client.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,62 @@ static void update_group_attrs(struct seq_ump_client *client)
290290
}
291291
}
292292

293+
/* create a UMP Endpoint port */
294+
static int create_ump_endpoint_port(struct seq_ump_client *client)
295+
{
296+
struct snd_seq_port_info *port;
297+
struct snd_seq_port_callback pcallbacks;
298+
unsigned int rawmidi_info = client->ump->core.info_flags;
299+
int err;
300+
301+
port = kzalloc(sizeof(*port), GFP_KERNEL);
302+
if (!port)
303+
return -ENOMEM;
304+
305+
port->addr.client = client->seq_client;
306+
port->addr.port = 0; /* fixed */
307+
port->flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT;
308+
port->capability = SNDRV_SEQ_PORT_CAP_UMP_ENDPOINT;
309+
if (rawmidi_info & SNDRV_RAWMIDI_INFO_INPUT) {
310+
port->capability |= SNDRV_SEQ_PORT_CAP_READ |
311+
SNDRV_SEQ_PORT_CAP_SYNC_READ |
312+
SNDRV_SEQ_PORT_CAP_SUBS_READ;
313+
port->direction |= SNDRV_SEQ_PORT_DIR_INPUT;
314+
}
315+
if (rawmidi_info & SNDRV_RAWMIDI_INFO_OUTPUT) {
316+
port->capability |= SNDRV_SEQ_PORT_CAP_WRITE |
317+
SNDRV_SEQ_PORT_CAP_SYNC_WRITE |
318+
SNDRV_SEQ_PORT_CAP_SUBS_WRITE;
319+
port->direction |= SNDRV_SEQ_PORT_DIR_OUTPUT;
320+
}
321+
if (rawmidi_info & SNDRV_RAWMIDI_INFO_DUPLEX)
322+
port->capability |= SNDRV_SEQ_PORT_CAP_DUPLEX;
323+
port->ump_group = 0; /* no associated group, no conversion */
324+
port->type = SNDRV_SEQ_PORT_TYPE_MIDI_UMP |
325+
SNDRV_SEQ_PORT_TYPE_HARDWARE |
326+
SNDRV_SEQ_PORT_TYPE_PORT;
327+
port->midi_channels = 16;
328+
strcpy(port->name, "MIDI 2.0");
329+
memset(&pcallbacks, 0, sizeof(pcallbacks));
330+
pcallbacks.owner = THIS_MODULE;
331+
pcallbacks.private_data = client;
332+
if (rawmidi_info & SNDRV_RAWMIDI_INFO_INPUT) {
333+
pcallbacks.subscribe = seq_ump_subscribe;
334+
pcallbacks.unsubscribe = seq_ump_unsubscribe;
335+
}
336+
if (rawmidi_info & SNDRV_RAWMIDI_INFO_OUTPUT) {
337+
pcallbacks.use = seq_ump_use;
338+
pcallbacks.unuse = seq_ump_unuse;
339+
pcallbacks.event_input = seq_ump_process_event;
340+
}
341+
port->kernel = &pcallbacks;
342+
err = snd_seq_kernel_client_ctl(client->seq_client,
343+
SNDRV_SEQ_IOCTL_CREATE_PORT,
344+
port);
345+
kfree(port);
346+
return err;
347+
}
348+
293349
/* release the client resources */
294350
static void seq_ump_client_free(struct seq_ump_client *client)
295351
{
@@ -353,6 +409,10 @@ static int snd_seq_ump_probe(struct device *_dev)
353409
goto error;
354410
}
355411

412+
err = create_ump_endpoint_port(client);
413+
if (err < 0)
414+
goto error;
415+
356416
ump->seq_client = client;
357417
ump->seq_ops = &seq_ump_ops;
358418
return 0;

0 commit comments

Comments
 (0)