All of lore.kernel.org
 help / color / mirror / Atom feed
From: Takashi Iwai <tiwai@suse.de>
To: alsa-devel@alsa-project.org
Cc: linux-kernel@vger.kernel.org
Subject: [PATCH 31/36] ALSA: seq: Bind UMP device
Date: Fri, 19 May 2023 11:31:09 +0200	[thread overview]
Message-ID: <20230519093114.28813-32-tiwai@suse.de> (raw)
In-Reply-To: <20230519093114.28813-1-tiwai@suse.de>

This patch introduces a new ALSA sequencer client for the kernel UMP
object, snd-seq-ump-client.  It's a UMP version of snd-seq-midi
driver, while this driver creates a sequencer client per UMP endpoint
which contains (fixed) 16 ports.

The UMP rawmidi device is opened in APPEND mode for output, so that
multiple sequencer clients can share the same UMP endpoint, as well as
the legacy UMP rawmidi devices that are opened in APPEND mode, too.
For input, on the other hand, the incoming data is processed on the
fly in the dedicated hook, hence it doesn't open a rawmidi device.

The UMP packet group is updated upon delivery depending on the target
sequencer port (which corresponds to the actual UMP group).

Each sequencer port sets a new port type bit,
SNDRV_SEQ_PORT_TYPE_MIDI_UMP, in addition to the other standard
types for MIDI.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 include/sound/seq_device.h      |   1 +
 include/sound/ump.h             |  15 +-
 include/uapi/sound/asequencer.h |   1 +
 sound/core/seq/Kconfig          |   5 +
 sound/core/seq/Makefile         |   2 +
 sound/core/seq/seq_ump_client.c | 389 ++++++++++++++++++++++++++++++++
 sound/core/ump.c                |  28 ++-
 7 files changed, 439 insertions(+), 2 deletions(-)
 create mode 100644 sound/core/seq/seq_ump_client.c

diff --git a/include/sound/seq_device.h b/include/sound/seq_device.h
index 8899affe9155..dead74b022f4 100644
--- a/include/sound/seq_device.h
+++ b/include/sound/seq_device.h
@@ -78,5 +78,6 @@ void snd_seq_driver_unregister(struct snd_seq_driver *drv);
  */
 #define SNDRV_SEQ_DEV_ID_MIDISYNTH	"seq-midi"
 #define SNDRV_SEQ_DEV_ID_OPL3		"opl3-synth"
+#define SNDRV_SEQ_DEV_ID_UMP		"seq-ump-client"
 
 #endif /* __SOUND_SEQ_DEVICE_H */
diff --git a/include/sound/ump.h b/include/sound/ump.h
index 45f4c9b673b5..e4fdf7cccf12 100644
--- a/include/sound/ump.h
+++ b/include/sound/ump.h
@@ -11,6 +11,7 @@ struct snd_ump_endpoint;
 struct snd_ump_block;
 struct snd_ump_ops;
 struct ump_cvt_to_ump;
+struct snd_seq_ump_ops;
 
 struct snd_ump_endpoint {
 	struct snd_rawmidi core;	/* raw UMP access */
@@ -30,9 +31,9 @@ struct snd_ump_endpoint {
 	int input_buf_head;
 	int input_pending;
 
-#if IS_ENABLED(CONFIG_SND_UMP_LEGACY_RAWMIDI)
 	struct mutex open_mutex;
 
+#if IS_ENABLED(CONFIG_SND_UMP_LEGACY_RAWMIDI)
 	spinlock_t legacy_locks[2];
 	struct snd_rawmidi *legacy_rmidi;
 	struct snd_rawmidi_substream *legacy_substreams[2][SNDRV_UMP_MAX_GROUPS];
@@ -42,6 +43,12 @@ struct snd_ump_endpoint {
 	struct snd_rawmidi_file legacy_out_rfile;
 	struct ump_cvt_to_ump *out_cvts;
 #endif
+
+#if IS_ENABLED(CONFIG_SND_SEQUENCER)
+	struct snd_seq_device *seq_dev;
+	const struct snd_seq_ump_ops *seq_ops;
+	void *seq_client;
+#endif
 };
 
 /* ops filled by UMP drivers */
@@ -52,6 +59,12 @@ struct snd_ump_ops {
 	void (*drain)(struct snd_ump_endpoint *ump, int dir);
 };
 
+/* ops filled by sequencer binding */
+struct snd_seq_ump_ops {
+	void (*input_receive)(struct snd_ump_endpoint *ump,
+			      const u32 *data, int words);
+};
+
 struct snd_ump_block {
 	struct snd_ump_block_info info;
 	struct snd_ump_endpoint *ump;
diff --git a/include/uapi/sound/asequencer.h b/include/uapi/sound/asequencer.h
index c4632bd9d3a0..3fa6b17aa7a2 100644
--- a/include/uapi/sound/asequencer.h
+++ b/include/uapi/sound/asequencer.h
@@ -439,6 +439,7 @@ struct snd_seq_remove_events {
 #define SNDRV_SEQ_PORT_TYPE_MIDI_XG	(1<<4)	/* XG compatible device */
 #define SNDRV_SEQ_PORT_TYPE_MIDI_MT32	(1<<5)	/* MT-32 compatible device */
 #define SNDRV_SEQ_PORT_TYPE_MIDI_GM2	(1<<6)	/* General MIDI 2 compatible device */
+#define SNDRV_SEQ_PORT_TYPE_MIDI_UMP	(1<<7)	/* UMP */
 
 /* other standards...*/
 #define SNDRV_SEQ_PORT_TYPE_SYNTH	(1<<10)	/* Synth device (no MIDI compatible - direct wavetable) */
diff --git a/sound/core/seq/Kconfig b/sound/core/seq/Kconfig
index f8336134153e..c14981daf943 100644
--- a/sound/core/seq/Kconfig
+++ b/sound/core/seq/Kconfig
@@ -62,6 +62,7 @@ config SND_SEQ_VIRMIDI
 
 config SND_SEQ_UMP
 	bool "Support for UMP events"
+	default y if SND_SEQ_UMP_CLIENT
 	help
 	  Say Y here to enable the support for handling UMP (Universal MIDI
 	  Packet) events via ALSA sequencer infrastructure, which is an
@@ -69,4 +70,8 @@ config SND_SEQ_UMP
 	  It includes the automatic conversion of ALSA sequencer events
 	  among legacy and UMP clients.
 
+config SND_SEQ_UMP_CLIENT
+	tristate
+	def_tristate SND_UMP
+
 endif # SND_SEQUENCER
diff --git a/sound/core/seq/Makefile b/sound/core/seq/Makefile
index ba264a695643..990eec7c83ad 100644
--- a/sound/core/seq/Makefile
+++ b/sound/core/seq/Makefile
@@ -14,12 +14,14 @@ snd-seq-midi-emul-objs := seq_midi_emul.o
 snd-seq-midi-event-objs := seq_midi_event.o
 snd-seq-dummy-objs := seq_dummy.o
 snd-seq-virmidi-objs := seq_virmidi.o
+snd-seq-ump-client-objs := seq_ump_client.o
 
 obj-$(CONFIG_SND_SEQUENCER) += snd-seq.o
 obj-$(CONFIG_SND_SEQUENCER_OSS) += oss/
 
 obj-$(CONFIG_SND_SEQ_DUMMY) += snd-seq-dummy.o
 obj-$(CONFIG_SND_SEQ_MIDI) += snd-seq-midi.o
+obj-$(CONFIG_SND_SEQ_UMP_CLIENT) += snd-seq-ump-client.o
 obj-$(CONFIG_SND_SEQ_MIDI_EMUL) += snd-seq-midi-emul.o
 obj-$(CONFIG_SND_SEQ_MIDI_EVENT) += snd-seq-midi-event.o
 obj-$(CONFIG_SND_SEQ_VIRMIDI) += snd-seq-virmidi.o
diff --git a/sound/core/seq/seq_ump_client.c b/sound/core/seq/seq_ump_client.c
new file mode 100644
index 000000000000..8d360655ff5d
--- /dev/null
+++ b/sound/core/seq/seq_ump_client.c
@@ -0,0 +1,389 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* ALSA sequencer binding for UMP device */
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/mutex.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include <asm/byteorder.h>
+#include <sound/core.h>
+#include <sound/ump.h>
+#include <sound/seq_kernel.h>
+#include <sound/seq_device.h>
+#include "seq_clientmgr.h"
+
+struct seq_ump_client;
+struct seq_ump_group;
+
+enum {
+	STR_IN = SNDRV_RAWMIDI_STREAM_INPUT,
+	STR_OUT = SNDRV_RAWMIDI_STREAM_OUTPUT
+};
+
+/* object per UMP group; corresponding to a sequencer port */
+struct seq_ump_group {
+	int group;			/* group index (0-based) */
+	unsigned int dir_bits;		/* directions */
+	bool active;			/* activeness */
+	char name[64];			/* seq port name */
+};
+
+/* context for UMP input parsing, per EP */
+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 */
+	struct snd_rawmidi_file out_rfile; /* rawmidi for output */
+	struct seq_ump_input_buffer input; /* input parser context */
+	struct seq_ump_group groups[SNDRV_UMP_MAX_GROUPS]; /* table of groups */
+};
+
+/* 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;
+
+	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;
+
+	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;
+	int err = 0;
+
+	mutex_lock(&ump->open_mutex);
+	if (dir == STR_OUT && !client->opened[dir]) {
+		err = snd_rawmidi_kernel_open(&ump->core, 0,
+					      SNDRV_RAWMIDI_LFLG_OUTPUT |
+					      SNDRV_RAWMIDI_LFLG_APPEND,
+					      &client->out_rfile);
+		if (err < 0)
+			goto unlock;
+	}
+	client->opened[dir]++;
+ unlock:
+	mutex_unlock(&ump->open_mutex);
+	return err;
+}
+
+/* close the rawmidi */
+static int seq_ump_client_close(struct seq_ump_client *client, int dir)
+{
+	struct snd_ump_endpoint *ump = client->ump;
+
+	mutex_lock(&ump->open_mutex);
+	if (!--client->opened[dir])
+		if (dir == STR_OUT)
+			snd_rawmidi_kernel_release(&client->out_rfile);
+	mutex_unlock(&ump->open_mutex);
+	return 0;
+}
+
+/* sequencer subscription ops for each client */
+static int seq_ump_subscribe(void *pdata, struct snd_seq_port_subscribe *info)
+{
+	struct seq_ump_client *client = pdata;
+
+	return seq_ump_client_open(client, STR_IN);
+}
+
+static int seq_ump_unsubscribe(void *pdata, struct snd_seq_port_subscribe *info)
+{
+	struct seq_ump_client *client = pdata;
+
+	return seq_ump_client_close(client, STR_IN);
+}
+
+static int seq_ump_use(void *pdata, struct snd_seq_port_subscribe *info)
+{
+	struct seq_ump_client *client = pdata;
+
+	return seq_ump_client_open(client, STR_OUT);
+}
+
+static int seq_ump_unuse(void *pdata, struct snd_seq_port_subscribe *info)
+{
+	struct seq_ump_client *client = pdata;
+
+	return seq_ump_client_close(client, STR_OUT);
+}
+
+/* fill port_info from the given UMP EP and group info */
+static void fill_port_info(struct snd_seq_port_info *port,
+			   struct seq_ump_client *client,
+			   struct seq_ump_group *group)
+{
+	unsigned int rawmidi_info = client->ump->core.info_flags;
+
+	port->addr.client = client->seq_client;
+	port->addr.port = ump_group_to_seq_port(group->group);
+	port->capability = 0;
+	if (rawmidi_info & SNDRV_RAWMIDI_INFO_OUTPUT)
+		port->capability |= SNDRV_SEQ_PORT_CAP_WRITE |
+			SNDRV_SEQ_PORT_CAP_SYNC_WRITE |
+			SNDRV_SEQ_PORT_CAP_SUBS_WRITE;
+	if (rawmidi_info & SNDRV_RAWMIDI_INFO_INPUT)
+		port->capability |= SNDRV_SEQ_PORT_CAP_READ |
+			SNDRV_SEQ_PORT_CAP_SYNC_READ |
+			SNDRV_SEQ_PORT_CAP_SUBS_READ;
+	if (rawmidi_info & SNDRV_RAWMIDI_INFO_DUPLEX)
+		port->capability |= SNDRV_SEQ_PORT_CAP_DUPLEX;
+	if (group->dir_bits & (1 << STR_IN))
+		port->direction |= SNDRV_SEQ_PORT_DIR_INPUT;
+	if (group->dir_bits & (1 << STR_OUT))
+		port->direction |= SNDRV_SEQ_PORT_DIR_OUTPUT;
+	port->ump_group = group->group + 1;
+	if (!group->active)
+		port->capability |= SNDRV_SEQ_PORT_CAP_INACTIVE;
+	port->type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |
+		SNDRV_SEQ_PORT_TYPE_MIDI_UMP |
+		SNDRV_SEQ_PORT_TYPE_HARDWARE |
+		SNDRV_SEQ_PORT_TYPE_PORT;
+	port->midi_channels = 16;
+	if (*group->name)
+		snprintf(port->name, sizeof(port->name), "Group %d (%s)",
+			 group->group + 1, group->name);
+	else
+		sprintf(port->name, "Group %d", group->group + 1);
+}
+
+/* create a new sequencer port per UMP group */
+static int seq_ump_group_init(struct seq_ump_client *client, int group_index)
+{
+	struct seq_ump_group *group = &client->groups[group_index];
+	struct snd_seq_port_info *port;
+	struct snd_seq_port_callback pcallbacks;
+	int err;
+
+	port = kzalloc(sizeof(*port), GFP_KERNEL);
+	if (!port) {
+		err = -ENOMEM;
+		goto error;
+	}
+
+	fill_port_info(port, client, group);
+	port->flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT;
+	memset(&pcallbacks, 0, sizeof(pcallbacks));
+	pcallbacks.owner = THIS_MODULE;
+	pcallbacks.private_data = client;
+	pcallbacks.subscribe = seq_ump_subscribe;
+	pcallbacks.unsubscribe = seq_ump_unsubscribe;
+	pcallbacks.use = seq_ump_use;
+	pcallbacks.unuse = seq_ump_unuse;
+	pcallbacks.event_input = seq_ump_process_event;
+	port->kernel = &pcallbacks;
+	err = snd_seq_kernel_client_ctl(client->seq_client,
+					SNDRV_SEQ_IOCTL_CREATE_PORT,
+					port);
+ error:
+	kfree(port);
+	return err;
+}
+
+/* update dir_bits and active flag for all groups in the client */
+static void update_group_attrs(struct seq_ump_client *client)
+{
+	struct snd_ump_block *fb;
+	struct seq_ump_group *group;
+	int i;
+
+	for (i = 0; i < SNDRV_UMP_MAX_GROUPS; i++) {
+		group = &client->groups[i];
+		*group->name = 0;
+		group->dir_bits = 0;
+		group->active = 0;
+		group->group = i;
+	}
+
+	list_for_each_entry(fb, &client->ump->block_list, list) {
+		if (fb->info.first_group < 0 ||
+		    fb->info.first_group + fb->info.num_groups > SNDRV_UMP_MAX_GROUPS)
+			break;
+		group = &client->groups[fb->info.first_group];
+		for (i = 0; i < fb->info.num_groups; i++, group++) {
+			if (fb->info.active)
+				group->active = 1;
+			switch (fb->info.direction) {
+			case SNDRV_UMP_DIR_INPUT:
+				group->dir_bits |= (1 << STR_IN);
+				break;
+			case SNDRV_UMP_DIR_OUTPUT:
+				group->dir_bits |= (1 << STR_OUT);
+				break;
+			case SNDRV_UMP_DIR_BIDIRECTION:
+				group->dir_bits |= (1 << STR_OUT) | (1 << STR_IN);
+				break;
+			}
+			if (!*fb->info.name)
+				continue;
+			if (!*group->name) {
+				/* store the first matching name */
+				strscpy(group->name, fb->info.name,
+					sizeof(group->name));
+			} else {
+				/* when overlapping, concat names */
+				strlcat(group->name, ", ", sizeof(group->name));
+				strlcat(group->name, fb->info.name,
+					sizeof(group->name));
+			}
+		}
+	}
+}
+
+/* release the client resources */
+static void seq_ump_client_free(struct seq_ump_client *client)
+{
+	if (client->seq_client >= 0)
+		snd_seq_delete_kernel_client(client->seq_client);
+
+	client->ump->seq_ops = NULL;
+	client->ump->seq_client = NULL;
+
+	kfree(client);
+}
+
+/* update the MIDI version for the given client */
+static void setup_client_midi_version(struct seq_ump_client *client)
+{
+	struct snd_seq_client *cptr;
+
+	cptr = snd_seq_kernel_client_get(client->seq_client);
+	if (!cptr)
+		return;
+	if (client->ump->info.protocol & SNDRV_UMP_EP_INFO_PROTO_MIDI2)
+		cptr->midi_version = SNDRV_SEQ_CLIENT_UMP_MIDI_2_0;
+	else
+		cptr->midi_version = SNDRV_SEQ_CLIENT_UMP_MIDI_1_0;
+	snd_seq_kernel_client_put(cptr);
+}
+
+static const struct snd_seq_ump_ops seq_ump_ops = {
+	.input_receive = seq_ump_input_receive,
+};
+
+/* create a sequencer client and ports for the given UMP endpoint */
+static int snd_seq_ump_probe(struct device *_dev)
+{
+	struct snd_seq_device *dev = to_seq_dev(_dev);
+	struct snd_ump_endpoint *ump = dev->private_data;
+	struct snd_card *card = dev->card;
+	struct seq_ump_client *client;
+	int p, err;
+
+	client = kzalloc(sizeof(*client), GFP_KERNEL);
+	if (!client)
+		return -ENOMEM;
+
+	client->ump = ump;
+
+	client->seq_client =
+		snd_seq_create_kernel_client(card, ump->core.device,
+					     ump->core.name);
+	if (client->seq_client < 0) {
+		err = client->seq_client;
+		goto error;
+	}
+
+	setup_client_midi_version(client);
+	update_group_attrs(client);
+
+	for (p = 0; p < SNDRV_UMP_MAX_GROUPS; p++) {
+		err = seq_ump_group_init(client, p);
+		if (err < 0)
+			goto error;
+	}
+
+	ump->seq_client = client;
+	ump->seq_ops = &seq_ump_ops;
+	return 0;
+
+ error:
+	seq_ump_client_free(client);
+	return err;
+}
+
+/* remove a sequencer client */
+static int snd_seq_ump_remove(struct device *_dev)
+{
+	struct snd_seq_device *dev = to_seq_dev(_dev);
+	struct snd_ump_endpoint *ump = dev->private_data;
+
+	if (ump->seq_client)
+		seq_ump_client_free(ump->seq_client);
+	return 0;
+}
+
+static struct snd_seq_driver seq_ump_driver = {
+	.driver = {
+		.name = KBUILD_MODNAME,
+		.probe = snd_seq_ump_probe,
+		.remove = snd_seq_ump_remove,
+	},
+	.id = SNDRV_SEQ_DEV_ID_UMP,
+	.argsize = 0,
+};
+
+module_snd_seq_driver(seq_ump_driver);
+
+MODULE_DESCRIPTION("ALSA sequencer client for UMP rawmidi");
+MODULE_LICENSE("GPL");
diff --git a/sound/core/ump.c b/sound/core/ump.c
index 176789090896..759124e0804d 100644
--- a/sound/core/ump.c
+++ b/sound/core/ump.c
@@ -132,8 +132,8 @@ int snd_ump_endpoint_new(struct snd_card *card, char *id, int device,
 	if (!ump)
 		return -ENOMEM;
 	INIT_LIST_HEAD(&ump->block_list);
-#if IS_ENABLED(CONFIG_SND_UMP_LEGACY_RAWMIDI)
 	mutex_init(&ump->open_mutex);
+#if IS_ENABLED(CONFIG_SND_UMP_LEGACY_RAWMIDI)
 	spin_lock_init(&ump->legacy_locks[0]);
 	spin_lock_init(&ump->legacy_locks[1]);
 #endif
@@ -166,8 +166,30 @@ EXPORT_SYMBOL_GPL(snd_ump_endpoint_new);
  * Device register / unregister hooks;
  *  do nothing, placeholders for avoiding the default rawmidi handling
  */
+
+#if IS_ENABLED(CONFIG_SND_SEQUENCER)
+static void snd_ump_dev_seq_free(struct snd_seq_device *device)
+{
+	struct snd_ump_endpoint *ump = device->private_data;
+
+	ump->seq_dev = NULL;
+}
+#endif
+
 static int snd_ump_dev_register(struct snd_rawmidi *rmidi)
 {
+#if IS_ENABLED(CONFIG_SND_SEQUENCER)
+	struct snd_ump_endpoint *ump = rawmidi_to_ump(rmidi);
+	int err;
+
+	err = snd_seq_device_new(ump->core.card, ump->core.device,
+				 SNDRV_SEQ_DEV_ID_UMP, 0, &ump->seq_dev);
+	if (err < 0)
+		return err;
+	ump->seq_dev->private_data = ump;
+	ump->seq_dev->private_free = snd_ump_dev_seq_free;
+	snd_device_register(ump->core.card, ump->seq_dev);
+#endif
 	return 0;
 }
 
@@ -280,6 +302,10 @@ int snd_ump_receive(struct snd_ump_endpoint *ump, const u32 *buffer, int count)
 		n = snd_ump_receive_ump_val(ump, *p++);
 		if (!n)
 			continue;
+#if IS_ENABLED(CONFIG_SND_SEQUENCER)
+		if (ump->seq_ops)
+			ump->seq_ops->input_receive(ump, ump->input_buf, n);
+#endif
 		process_legacy_input(ump, ump->input_buf, n);
 	}
 
-- 
2.35.3


  parent reply	other threads:[~2023-05-19  9:33 UTC|newest]

Thread overview: 89+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-05-19  9:30 [PATCH 00/36] ALSA: Add MIDI 2.0 support Takashi Iwai
2023-05-19  9:30 ` [PATCH 01/36] ALSA: rawmidi: Pass rawmidi directly to snd_rawmidi_kernel_open() Takashi Iwai
2023-05-22  5:40   ` Jaroslav Kysela
2023-05-19  9:30 ` [PATCH 02/36] ALSA: rawmidi: Add ioctl callback to snd_rawmidi_global_ops Takashi Iwai
2023-05-22  5:41   ` Jaroslav Kysela
2023-05-19  9:30 ` [PATCH 03/36] ALSA: rawmidi: UMP support Takashi Iwai
2023-05-22  6:34   ` Jaroslav Kysela
2023-05-22  7:21     ` Takashi Iwai
2023-05-22  8:08       ` Jaroslav Kysela
2023-05-22 10:27         ` Takashi Iwai
2023-05-22 12:27           ` Takashi Iwai
2023-05-22 16:22             ` Takashi Iwai
2023-05-22 19:01               ` Jaroslav Kysela
2023-05-19  9:30 ` [PATCH 04/36] ALSA: rawmidi: Skip UMP devices at SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE Takashi Iwai
2023-05-22  6:36   ` Jaroslav Kysela
2023-05-22  7:04     ` Takashi Iwai
2023-05-19  9:30 ` [PATCH 05/36] ALSA: ump: Additional proc output Takashi Iwai
2023-05-22  6:37   ` Jaroslav Kysela
2023-05-19  9:30 ` [PATCH 06/36] ALSA: usb-audio: Manage number of rawmidis globally Takashi Iwai
2023-05-22  6:39   ` Jaroslav Kysela
2023-05-19  9:30 ` [PATCH 07/36] ALSA: usb-audio: Define USB MIDI 2.0 specs Takashi Iwai
2023-05-19  9:46   ` Greg Kroah-Hartman
2023-05-22  6:41   ` Jaroslav Kysela
2023-05-19  9:30 ` [PATCH 08/36] ALSA: usb-audio: USB MIDI 2.0 UMP support Takashi Iwai
2023-05-22  6:47   ` Jaroslav Kysela
2023-05-19  9:30 ` [PATCH 09/36] ALSA: usb-audio: Get UMP EP name string from USB interface Takashi Iwai
2023-05-22  6:48   ` Jaroslav Kysela
2023-05-19  9:30 ` [PATCH 10/36] ALSA: usb-audio: Trim superfluous "MIDI" suffix from UMP EP name Takashi Iwai
2023-05-22  6:49   ` Jaroslav Kysela
2023-05-19  9:30 ` [PATCH 11/36] ALSA: usb-audio: Create UMP blocks from USB MIDI GTBs Takashi Iwai
2023-05-22  6:50   ` Jaroslav Kysela
2023-05-19  9:30 ` [PATCH 12/36] ALSA: ump: Redirect rawmidi substream access via own helpers Takashi Iwai
2023-05-22  6:54   ` Jaroslav Kysela
2023-05-19  9:30 ` [PATCH 13/36] ALSA: ump: Add legacy raw MIDI support Takashi Iwai
2023-05-22  7:00   ` Jaroslav Kysela
2023-05-19  9:30 ` [PATCH 14/36] ALSA: usb-audio: Enable the " Takashi Iwai
2023-05-22  7:02   ` Jaroslav Kysela
2023-05-19  9:30 ` [PATCH 15/36] ALSA: usb-audio: Inform inconsistent protocols in GTBs Takashi Iwai
2023-05-22  7:03   ` Jaroslav Kysela
2023-05-19  9:30 ` [PATCH 16/36] ALSA: seq: Clear padded bytes at expanding events Takashi Iwai
2023-05-22  7:04   ` Jaroslav Kysela
2023-05-19  9:30 ` [PATCH 17/36] ALSA: seq: Add snd_seq_expand_var_event_at() helper Takashi Iwai
2023-05-22  7:06   ` Jaroslav Kysela
2023-05-19  9:30 ` [PATCH 18/36] ALSA: seq: Treat snd_seq_client object directly in client drivers Takashi Iwai
2023-05-22  7:09   ` Jaroslav Kysela
2023-05-19  9:30 ` [PATCH 19/36] ALSA: seq: Drop dead code for the old broadcast support Takashi Iwai
2023-05-22  7:11   ` Jaroslav Kysela
2023-05-19  9:30 ` [PATCH 20/36] ALSA: seq: Check the conflicting port at port creation Takashi Iwai
2023-05-19 16:21   ` kernel test robot
2023-05-22  7:13   ` Jaroslav Kysela
2023-05-19  9:30 ` [PATCH 21/36] ALSA: seq: Check validity before creating a port object Takashi Iwai
2023-05-22  7:14   ` Jaroslav Kysela
2023-05-19  9:31 ` [PATCH 22/36] ALSA: seq: Prohibit creating ports with special numbers Takashi Iwai
2023-05-22  7:15   ` Jaroslav Kysela
2023-05-19  9:31 ` [PATCH 23/36] ALSA: seq: Introduce SNDRV_SEQ_IOCTL_USER_PVERSION ioctl Takashi Iwai
2023-05-22  7:32   ` Jaroslav Kysela
2023-05-19  9:31 ` [PATCH 24/36] ALSA: seq: Add UMP support Takashi Iwai
2023-05-22  7:34   ` Jaroslav Kysela
2023-05-22  8:00     ` Takashi Iwai
2023-05-22 10:31       ` Takashi Iwai
2023-05-22 11:59         ` Jaroslav Kysela
2023-05-19  9:31 ` [PATCH 25/36] ALSA: seq: Add port inactive flag Takashi Iwai
2023-05-22  7:35   ` Jaroslav Kysela
2023-05-19  9:31 ` [PATCH 26/36] ALSA: seq: Support MIDI 2.0 UMP Endpoint port Takashi Iwai
2023-05-22  7:37   ` Jaroslav Kysela
2023-05-19  9:31 ` [PATCH 27/36] ALSA: seq: Add port direction to snd_seq_port_info Takashi Iwai
2023-05-22  7:43   ` Jaroslav Kysela
2023-05-19  9:31 ` [PATCH 28/36] ALSA: seq: Add UMP group number " Takashi Iwai
2023-05-22  7:44   ` Jaroslav Kysela
2023-05-19  9:31 ` [PATCH 29/36] ALSA: seq: Automatic conversion of UMP events Takashi Iwai
2023-05-22  7:48   ` Jaroslav Kysela
2023-05-19  9:31 ` [PATCH 30/36] ALSA: seq: Allow suppressing UMP conversions Takashi Iwai
2023-05-22  7:49   ` Jaroslav Kysela
2023-05-19  9:31 ` Takashi Iwai [this message]
2023-05-22  7:52   ` [PATCH 31/36] ALSA: seq: Bind UMP device Jaroslav Kysela
2023-05-19  9:31 ` [PATCH 32/36] ALSA: seq: ump: Create UMP Endpoint port for broadcast Takashi Iwai
2023-05-22  7:52   ` Jaroslav Kysela
2023-05-19  9:31 ` [PATCH 33/36] ALSA: seq: Add ioctls for client UMP info query and setup Takashi Iwai
2023-05-22  7:54   ` Jaroslav Kysela
2023-05-19  9:31 ` [PATCH 34/36] ALSA: seq: Print UMP Endpoint and Block information in proc outputs Takashi Iwai
2023-05-19 11:44   ` kernel test robot
2023-05-22  7:55   ` Jaroslav Kysela
2023-05-19  9:31 ` [PATCH 35/36] ALSA: seq: Add UMP group filter Takashi Iwai
2023-05-22  7:56   ` Jaroslav Kysela
2023-05-19  9:31 ` [PATCH 36/36] ALSA: docs: Add MIDI 2.0 documentation Takashi Iwai
2023-05-19 23:02   ` kernel test robot
2023-05-22  7:58   ` Jaroslav Kysela
2023-06-13  3:22   ` happy.debugging
2023-06-13  6:01     ` Takashi Iwai

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230519093114.28813-32-tiwai@suse.de \
    --to=tiwai@suse.de \
    --cc=alsa-devel@alsa-project.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.