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: Support MIDI 2.0 UMP Endpoint port

This is an extension to ALSA sequencer infrastructure to support the
MIDI 2.0 UMP Endpoint port. It's a "catch-all" port that is supposed
to be present for each UMP Endpoint. When this port is read via
subscription, it sends any events from all ports (UMP Groups) found in
the same client.

A UMP Endpoint port can be created with the new capability bit
SNDRV_SEQ_PORT_CAP_UMP_ENDPOINT. Although the port assignment isn't
strictly defined, it should be the port number 0.

Reviewed-by: Jaroslav Kysela <perex@perex.cz>
Link: https://lore.kernel.org/r/20230523075358.9672-28-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>

+41 -8
+1
include/uapi/sound/asequencer.h
··· 428 428 #define SNDRV_SEQ_PORT_CAP_SUBS_WRITE (1<<6) /* allow write subscription */ 429 429 #define SNDRV_SEQ_PORT_CAP_NO_EXPORT (1<<7) /* routing not allowed */ 430 430 #define SNDRV_SEQ_PORT_CAP_INACTIVE (1<<8) /* inactive port */ 431 + #define SNDRV_SEQ_PORT_CAP_UMP_ENDPOINT (1<<9) /* MIDI 2.0 UMP Endpoint port */ 431 432 432 433 /* port type */ 433 434 #define SNDRV_SEQ_PORT_TYPE_SPECIFIC (1<<0) /* hardware specific */
+39 -8
sound/core/seq/seq_clientmgr.c
··· 239 239 mutex_init(&client->ports_mutex); 240 240 INIT_LIST_HEAD(&client->ports_list_head); 241 241 mutex_init(&client->ioctl_mutex); 242 + client->ump_endpoint_port = -1; 242 243 243 244 /* find free slot in the client table */ 244 245 spin_lock_irq(&clients_lock); ··· 681 680 /* 682 681 * send the event to all subscribers: 683 682 */ 684 - static int deliver_to_subscribers(struct snd_seq_client *client, 685 - struct snd_seq_event *event, 686 - int atomic, int hop) 683 + static int __deliver_to_subscribers(struct snd_seq_client *client, 684 + struct snd_seq_event *event, 685 + struct snd_seq_client_port *src_port, 686 + int atomic, int hop) 687 687 { 688 688 struct snd_seq_subscribers *subs; 689 689 int err, result = 0, num_ev = 0; 690 - struct snd_seq_client_port *src_port; 691 690 union __snd_seq_event event_saved; 692 691 size_t saved_size; 693 692 struct snd_seq_port_subs_info *grp; 694 693 695 - src_port = snd_seq_port_use_ptr(client, event->source.port); 696 - if (src_port == NULL) 697 - return -EINVAL; /* invalid source port */ 698 694 /* save original event record */ 699 695 saved_size = snd_seq_event_packet_size(event); 700 696 memcpy(&event_saved, event, saved_size); ··· 729 731 up_read(&grp->list_mutex); 730 732 memcpy(event, &event_saved, saved_size); 731 733 return (result < 0) ? result : num_ev; 734 + } 735 + 736 + static int deliver_to_subscribers(struct snd_seq_client *client, 737 + struct snd_seq_event *event, 738 + int atomic, int hop) 739 + { 740 + struct snd_seq_client_port *src_port; 741 + int ret = 0, ret2; 742 + 743 + src_port = snd_seq_port_use_ptr(client, event->source.port); 744 + if (src_port) { 745 + ret = __deliver_to_subscribers(client, event, src_port, atomic, hop); 746 + snd_seq_port_unlock(src_port); 747 + } 748 + 749 + if (client->ump_endpoint_port < 0 || 750 + event->source.port == client->ump_endpoint_port) 751 + return ret; 752 + 753 + src_port = snd_seq_port_use_ptr(client, client->ump_endpoint_port); 754 + if (!src_port) 755 + return ret; 756 + ret2 = __deliver_to_subscribers(client, event, src_port, atomic, hop); 757 + snd_seq_port_unlock(src_port); 758 + return ret2 < 0 ? ret2 : ret; 732 759 } 733 760 734 761 /* deliver an event to the destination port(s). ··· 1280 1257 return -EPERM; 1281 1258 if (client->type == USER_CLIENT && info->kernel) 1282 1259 return -EINVAL; 1260 + if ((info->capability & SNDRV_SEQ_PORT_CAP_UMP_ENDPOINT) && 1261 + client->ump_endpoint_port >= 0) 1262 + return -EBUSY; 1283 1263 1284 1264 if (info->flags & SNDRV_SEQ_PORT_FLG_GIVEN_PORT) 1285 1265 port_idx = info->addr.port; ··· 1312 1286 info->addr = port->addr; 1313 1287 1314 1288 snd_seq_set_port_info(port, info); 1289 + if (info->capability & SNDRV_SEQ_PORT_CAP_UMP_ENDPOINT) 1290 + client->ump_endpoint_port = port->addr.port; 1315 1291 snd_seq_system_client_ev_port_start(port->addr.client, port->addr.port); 1316 1292 snd_seq_port_unlock(port); 1317 1293 ··· 1333 1305 return -EPERM; 1334 1306 1335 1307 err = snd_seq_delete_port(client, info->addr.port); 1336 - if (err >= 0) 1308 + if (err >= 0) { 1309 + if (client->ump_endpoint_port == info->addr.port) 1310 + client->ump_endpoint_port = -1; 1337 1311 snd_seq_system_client_ev_port_exit(client->number, info->addr.port); 1312 + } 1338 1313 return err; 1339 1314 } 1340 1315
+1
sound/core/seq/seq_clientmgr.h
··· 50 50 struct mutex ports_mutex; 51 51 struct mutex ioctl_mutex; 52 52 int convert32; /* convert 32->64bit */ 53 + int ump_endpoint_port; 53 54 54 55 /* output pool */ 55 56 struct snd_seq_pool *pool; /* memory pool for this client */