Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

+60
+60
sound/core/seq/seq_ump_client.c
··· 290 290 } 291 291 } 292 292 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 + 293 349 /* release the client resources */ 294 350 static void seq_ump_client_free(struct seq_ump_client *client) 295 351 { ··· 408 352 if (err < 0) 409 353 goto error; 410 354 } 355 + 356 + err = create_ump_endpoint_port(client); 357 + if (err < 0) 358 + goto error; 411 359 412 360 ump->seq_client = client; 413 361 ump->seq_ops = &seq_ump_ops;